pax_global_header00006660000000000000000000000064136043540050014512gustar00rootroot0000000000000052 comment=08ebe85e154dfedcc8ac21fb96bef30beb956209 dub-1.19.0/000077500000000000000000000000001360435400500123545ustar00rootroot00000000000000dub-1.19.0/.codecov.yml000066400000000000000000000017001360435400500145750ustar00rootroot00000000000000# Documentation: https://docs.codecov.io/docs/codecov-yaml # Validate with: `curl --data-binary @.codecov.yml https://codecov.io/validate` codecov: notify: # We don't want to wait for the CodeCov report # See https://github.com/codecov/support/issues/312 require_ci_to_pass: false after_n_builds: 1 # send notifications after the first upload wait_for_ci: false bot: dlang-bot # At Travis, the PR is merged into `master` before the testsuite is run. # This allows CodeCov to adjust the resulting coverage diff, s.t. it matches # with the GitHub diff. # https://github.com/codecov/support/issues/363 # https://docs.codecov.io/v4.3.6/docs/comparing-commits allow_coverage_offsets: true coverage: precision: 3 round: down range: "80...100" # Learn more at https://docs.codecov.io/docs/commit-status status: project: off changes: off patch: default: informational: true comment: false dub-1.19.0/.editorconfig000066400000000000000000000002441360435400500150310ustar00rootroot00000000000000root = true [*.{c,h,d,di,dd,json}] end_of_line = lf insert_final_newline = true indent_style = tab indent_size = 4 trim_trailing_whitespace = true charset = utf-8 dub-1.19.0/.github/000077500000000000000000000000001360435400500137145ustar00rootroot00000000000000dub-1.19.0/.github/FUNDING.yml000066400000000000000000000002361360435400500155320ustar00rootroot00000000000000# https://help.github.com/en/articles/displaying-a-sponsor-button-in-your-repository open_collective: dlang custom: https://dlang.org/foundation/donate.html dub-1.19.0/.github/issue_template.md000066400000000000000000000011111360435400500172530ustar00rootroot00000000000000 ### System information - **dub version**: (e.g. dub 1.3.0) - **OS Platform and distribution**: (e.g. Windows 10, Linux Ubuntu 16.04) - **compiler version** (e.g. dmd-2.074.1) ### Bug Description ### How to reproduce? ### Expected Behavior ### Logs dub-1.19.0/.gitignore000066400000000000000000000015211360435400500143430ustar00rootroot00000000000000*.o *.obj *~ .dub .directory dub.selections.json docs.json __dummy.html # Ignore build files. /bin/dub /bin/__test__library-nonet__ /bin/__test__library__ /bin/dub-test-library /bin/libdub.a /bin/dub-* # Ignore files or directories created by the test suite. /test/test.log /test/custom-source-main-bug487/custom-source-main-bug487 /test/3-copyFiles/bin/ /test/ignore-hidden-1/ignore-hidden-1 /test/ignore-hidden-2/ignore-hidden-2 /test/expected-import-path-output /test/expected-string-import-path-output /test/expected-describe-data-1-list-output /test/expected-describe-data-2-dmd-output /test/expected-issue616-output /test/describe-project/dummy.dat /test/describe-project/dummy-dep1.dat /test/*/main/main /test/*/*test-library /test/*/*test-application /test/*/exec-simple # Ignore coverage files cov/ # Ignore auto-generated docs /docs dub-1.19.0/.travis.yml000066400000000000000000000056031360435400500144710ustar00rootroot00000000000000language: d dist: bionic addons: apt: packages: - libevent-dev script: - ./travis-ci.sh jobs: allow_failures: - d: gdc include: - stage: test d: dmd-2.089.0,dub env: [FRONTEND=2.089] - d: dmd-2.088.1,dub env: [FRONTEND=2.088] - d: dmd-2.077.1,dub env: [FRONTEND=2.077, COVERAGE=true] - d: dmd-2.076.1,dub env: [FRONTEND=2.076] - d: ldc-1.18.0,dub env: [FRONTEND=2.088] - stage: deploy d: ldc-1.18.0,dub os: osx script: echo "Deploying to GitHub releases ..." && ./release.sh deploy: - provider: releases file_glob: true file: bin/dub-*.tar.gz skip_cleanup: true api_key: $GH_REPO_TOKEN on: tags: true - d: ldc-1.18.0,dub script: echo "Deploying to GitHub releases ..." && ./release.sh env: [ARCH=32] addons: apt: packages: - g++-multilib - libcurl4-openssl-dev:i386 deploy: - provider: releases file_glob: true file: bin/dub-*.tar.gz skip_cleanup: true api_key: $GH_REPO_TOKEN on: tags: true - d: ldc-1.18.0,dub script: echo "Deploying to GitHub releases ..." && ./release.sh deploy: - provider: releases file_glob: true file: bin/dub-*.tar.gz skip_cleanup: true api_key: $GH_REPO_TOKEN on: tags: true - d: ldc-1.18.0,dub script: echo "Deploying to GitHub releases (win32) ..." && ./release-windows.sh addons: apt: packages: - p7zip-full deploy: - provider: releases file_glob: true file: bin/dub-*.zip skip_cleanup: true api_key: $GH_REPO_TOKEN on: tags: true - d: ldc-1.18.0,dub script: echo "Deploying to GitHub releases (win64) ..." && ARCH=64 ./release-windows.sh addons: apt: packages: - p7zip-full deploy: - provider: releases file_glob: true file: bin/dub-*.zip skip_cleanup: true api_key: $GH_REPO_TOKEN on: tags: true - stage: update-latest script: echo "Deploying to GitHub pages ..." && mkdir -p docs && git describe --abbrev=0 --tags > docs/LATEST deploy: - provider: pages skip_cleanup: true local_dir: docs github_token: $GH_REPO_TOKEN on: tags: true stages: - name: test if: type = pull_request or (type = push and branch = master) # Until deployment of the release binaries is fixed, always build them #- name: deploy #if: type = push and tag =~ ^v\d+\.\d+\.\d+[^-]*\$ # not a pre-release tag - name: update-latest if: type = push and tag =~ ^v\d+\.\d+\.\d+[^-]*\$ # not a pre-release tag dub-1.19.0/ARCHITECTURE.md000066400000000000000000000024361360435400500145650ustar00rootroot00000000000000## Architecture ![architecture](architecture.png) ## Terminology
Package
A locally available version of a dub package, consisting of sources, binaries, and described by it's dub.sdl/json file.
PackageSupplier
A source to search and fetch package versions (zip bundles) from.
PackageManager
Responsible to manage packages (fetched or add-local packages), and overrides.
PackageRecipe
Abstract description of package sources, targets, configurations, and build settings.
Generator
Responsible for generating a build recipe (e.g. CMakeLists.txt, VS .sln) for a package, config, and build type. Direct builds (dmd, rdmd) are also implemented as generators.
PackageDependency
Unresolved, abstract specification of a dependency, e.g. dependency "vibe-d" version="~>0.8.1".
DependencyResolver
Algorithm to resolve package dependencies to specific package versions (dub.selections.json), searching available package versions in package suppliers.
Target
A build output like a static library or executable.
BuildCache
Caches targets for a specific build id.
dub-1.19.0/CHANGELOG.md000066400000000000000000002113711360435400500141720ustar00rootroot00000000000000Changelog ========= v1.12.0 - 2018-11-01 ------------------- See v1.11.0 - 2018-09-01 ------------------- See v1.10.0 - 2018-07-01 ------------------- See v1.9.0 - 2018-05-01 ------------------- v1.8.1 - 2018-04-14 ------------------- - Fixed a regression in 1.8.0 that caused linker files specified as `sourceFiles` to not get inherited properly - [issue #1408][issue1408], [pull #1409][issue1409] - Fixed a regression in 1.8.0 that caused `mainSourceFile` to be passed twice to the compiler on Windows - [issue #1407][issue1407], [pull #1410][issue1410] [issue1407]: https://github.com/dlang/dub/issues/1407 [issue1408]: https://github.com/dlang/dub/issues/1408 [issue1409]: https://github.com/dlang/dub/issues/1409 [issue1410]: https://github.com/dlang/dub/issues/1410 v1.8.0 - 2018-03-01 ------------------- v1.7.2 - 2018-02-07 ------------------- - more reliable retries and fallback mirror usage - [pull #1339][issue1339] [issue1339]: https://github.com/dlang/dub/issues/1339 v1.7.1 - 2018-01-21 ------------------- - Timeout requests to query mirror instead of hanging - [pull #1338][issue1338] [issue1338]: https://github.com/dlang/dub/issues/1338 v1.7.0 - 2018-01-01 ------------------- v1.6.0 - 2017-11-01 ------------------- - The version list displayed for interactive package removal is now sorted - [pull #1225][issue1225], [issue #1224][issue1224] - File attributes of fetched packages are now preserved - [pull #1226][issue1226] - `http://code-mirror.dlang.io` is now used as a fallback for `code.dlang.org` - [pull #1190][issue1190] - Failed package downloads are now retried two more times (by Colin Grogan) - [pull #1198][issue1198] [issue1190]: https://github.com/dlang/dub/issues/1190 [issue1198]: https://github.com/dlang/dub/issues/1198 [issue1224]: https://github.com/dlang/dub/issues/1224 [issue1225]: https://github.com/dlang/dub/issues/1225 [issue1226]: https://github.com/dlang/dub/issues/1226 v1.5.0 - 2017-09-01 ------------------- - Allow digits in package names (by Chad Joan) - [pull #1165][issue1165] - Support the `no_proxy` environment variable for HTTP requests (by André Pany) - [pull #1162][issue1162], [issue #1159][issue1159] - Read additional registry URLs (semicolon separated) from DUB_REGISTRY env var - [pull #1173][issue1173] - Single file packages don't have to specify an explicit name anymore (will be inferred from the file name) - [pull #1081][issue1081] - Add support for the `--parallel` switch for `dub test` (currently only has an effect for `--build-mode=singleFile`) - [pull #1182][issue1182] - Improved error reporting for package download failures - [pull #1104][issue1104] - Fixed building the code base against Android/Bionic - [pull #1202][issue1202] - Extended the generated gitignore file (by Ryan Frame) - [pull #1050][issue1050] [issue1050]: https://github.com/dlang/dub/issues/1050 [issue1081]: https://github.com/dlang/dub/issues/1081 [issue1104]: https://github.com/dlang/dub/issues/1104 [issue1182]: https://github.com/dlang/dub/issues/1182 [issue1159]: https://github.com/dlang/dub/issues/1159 [issue1162]: https://github.com/dlang/dub/issues/1162 [issue1165]: https://github.com/dlang/dub/issues/1165 [issue1173]: https://github.com/dlang/dub/issues/1173 [issue1202]: https://github.com/dlang/dub/issues/1202 v1.4.1 - 2017-08-10 ------------------- This release is identical with 1.4.0. v1.4.0 - 2017-07-19 ------------------- - The copyright string is generated automatically by "dub init" - "dub init" lets the user retry to enter the package name if not valid (by NotSpooky) - [pull #1122][issue1122] - Improved collection speed for source/import files - [pull #1125][issue1125] - Fixed "dub init" to allow digits in package names (by chadjoan) - [pull #1165][issue1165] - Fixed a sub package build issue on Windows, where colons were used as part of the file name (by andre2007) - [issue #1130][issue1130], [pull #1137][issue1137] - Fixed failures to acquire a lock when fetching packages - [pull #1149][issue1149] [issue1122]: https://github.com/dlang/dub/issues/1122 [issue1125]: https://github.com/dlang/dub/issues/1125 [issue1130]: https://github.com/dlang/dub/issues/1130 [issue1137]: https://github.com/dlang/dub/issues/1137 [issue1149]: https://github.com/dlang/dub/issues/1149 [issue1165]: https://github.com/dlang/dub/issues/1165 v1.3.0 - 2017-04-10 ------------------- ### Features and improvements ### - Reduced the initialization time for "dub test" by several seconds by avoiding a complex regex - [pull #1078][issue1078] - Reduced cubic runtime complexity for collecting string import files to almost linear in the common case - [pull #1079][issue1079] - Compiler flag usage warnings are now only emitted for the root package, reducing build output noise - [a75023cd][commita75023cd] - Avoid redundant recreation of hard links for build targets (by Danny Milosavljevic aka daym) - [pull #1071][issue1071] ### Bug fixes ### - Fixed bogus rebuild of packages with no dependencies - [pull #1093][issue1093], [issue #1091][issue1091] - Fixed building with vibe-core instead of vibe.d 0.7.x - Fixed the VisualD generator to properly handle the "x86_mscoff" pseudoarchitecture - [4d416e73][commit4d416e73] [commita75023cd]: https://github.com/dlang/dub/commit/a75023cd050c055e81190bf7abc5793aba39852f [commit4d416e73]: https://github.com/dlang/dub/commit/4d416e730df872b552ee1dcfa8340c224a4e51fc [issue1071]: https://github.com/dlang/dub/issues/1071 [issue1078]: https://github.com/dlang/dub/issues/1078 [issue1079]: https://github.com/dlang/dub/issues/1079 [issue1091]: https://github.com/dlang/dub/issues/1091 [issue1093]: https://github.com/dlang/dub/issues/1093 v1.2.2 - 2017-03-09 ------------------- v1.2.1 - 2017-02-12 ------------------- ### Bug fixes ### - Fixed compile error when compiling with vibe.d versions prior to 0.8.0 - [9d25e5dd][commit9d25e5dd] - Fixed orphan format specifier error - [220b0128][commit220b0128] - Fixed test executable name generation causing sub package test builds to fail - [e6262373][commite6262373] - Fixed bogus warning message when compiling with `--arch x86_mscoff` (by Andrey Penechko aka MrSmith33) - [pull #1059][issue1059] - Fixed plaform specifiers to work for "x86_mscoff" - [86e85276][commit86e85276] [commit9d25e5dd]: https://github.com/dlang/dub/commit/9d25e5dd0337e9c054ff32c4b921f32603d29293 [commit220b0128]: https://github.com/dlang/dub/commit/220b01280041abbead57db6eec28e9279b9d7cf6 [commite6262373]: https://github.com/dlang/dub/commit/e6262373558591fa8754704fcc2e8ddafabf6671 [commit86e85276]: https://github.com/dlang/dub/commit/86e85276a7ff85c5cde4e1926c40e666a2b6bf78 [issue1059]: https://github.com/dlang/dub/issues/1059 v1.2.0 - 2017-01-22 ------------------- ### Features and improvements ### - Added an `--override-config` command line option to force selecting specific configurations for dependencies - [pull #1004][issue1004] - Added an `x86_mscoff` architecture corresponding to DMD's `-m32mscoff` flag (by John Colvin) - [pull #1007][issue1007] - Implemented selective dependency upgrades ("dub upgrade ") - [issue #1024][issue1024] - Multiple configurations with the same name are now detected and will cause a warning to be displayed - [issue #984][issue984] - Updated the Sublime Text generator and the Bash completion script to include the default "release-debug" build type (by p0nce) - [pull #1028][issue1028] - The `--force-remove` switch is scheduled for deprecation, as it didn't do anything for a while now - [pull #1023][issue1023] [issue984]: https://github.com/dlang/dub/issues/984 [issue1004]: https://github.com/dlang/dub/issues/1004 [issue1007]: https://github.com/dlang/dub/issues/1007 [issue1023]: https://github.com/dlang/dub/issues/1023 [issue1024]: https://github.com/dlang/dub/issues/1024 [issue1028]: https://github.com/dlang/dub/issues/1028 v1.1.2 - 2016-12-31 ------------------- ### Bug fixes ### - Fixes configuration resolution in diamond dependency settings - [issue #1005][issue1005], [pull #1006][issue1006] - Fixed path based package overrides ("dub add-override") - [issue #779][issue779] - Contains various diagnostic and error message improvements - [issue #957][issue957], [pull #1010][issue1010], [pull #1012][issue1012], [issue #1019][issue1019] [issue779]: https://github.com/dlang/dub/issues/779 [issue957]: https://github.com/dlang/dub/issues/957 [issue1005]: https://github.com/dlang/dub/issues/1005 [issue1006]: https://github.com/dlang/dub/issues/1006 [issue1010]: https://github.com/dlang/dub/issues/1010 [issue1012]: https://github.com/dlang/dub/issues/1012 [issue1019]: https://github.com/dlang/dub/issues/1019 v1.1.1 - 2016-11-30 ------------------- ### Bug fixes ### - Fixed a regression where path based dependencies were not properly resolved - [issue #934][issue934], [issue #959][issue959], [pull #962][issue962], [pull #969][issue969] - Fixed DMD separate compile/link detection code for the case where the compiler binary is not called "dmd" - [pull #966][issur966] - Fixed using the selected compiler for generated Sublime Text projects - [issue #931][issue931], [pull #983][issue983] - Fixed upgrading of optional dependencies (were ignored during the upgrade previously) - [issue #672][issue672], [pull #989][issue989] - Fixed automatic downloading of selected optional dependencies - [issue #990][issue990], [pull #991][issue991] [issue672]: https://github.com/dlang/dub/issues/672 [issue931]: https://github.com/dlang/dub/issues/931 [issue934]: https://github.com/dlang/dub/issues/934 [issue959]: https://github.com/dlang/dub/issues/959 [issue962]: https://github.com/dlang/dub/issues/962 [issue966]: https://github.com/dlang/dub/issues/966 [issue969]: https://github.com/dlang/dub/issues/969 [issue983]: https://github.com/dlang/dub/issues/983 [issue989]: https://github.com/dlang/dub/issues/989 [issue990]: https://github.com/dlang/dub/issues/990 [issue991]: https://github.com/dlang/dub/issues/991 v1.1.0 - 2016-10-31 ------------------- ### Features and improvements ### - Fixed compilation for DMD 2.072.0 (minimum supported frontend version is 2.065) - [pull #891][issue891] - Fixed compilation with the latest vibe.d 0.7.30 alpha versions (avoid `Bson.opDispatch`) - Single-file packages are now built locally unless the shebang syntax is used (still performs a build in the temporary folder in that case) - [issue #887][issue887], [pull #888][issue888] - DUB now searches for a configuration file in "../etc/dub/settings.json" (relative to the executable location), enabling distribution-specific configuration - [issue #895][issue895], [pull #897][issue897] - "dub remove" is now interactive in case of multiple matching package versions - [pull #879][issue879] - Added a "--stdout" switch to "dub convert" - [issue #932][issue932], [pull #933][issue933] ### Bug fixes ### - Pressing Ctrl+C during "dub init" now doesn't leave a half-initialized package behind - [issue #883][issue883], [pull #884][issue884] - Fixed handling of empty array directives in the SDLang recipe parser (e.g. a single `sourcePaths` directive with no arguments now properly avoids searching for default source directories) - Fixed a bad error message for missing dependencies that are referenced in the root package, as well as from a dependency - [issue #896][issue896] - Fixed naming of folders in generated Sublime Text projects (by p0nce) - [pull #918][issue918] - Fixed the workaround for "dub test" and modern vibe.d projects (proper fix is planned after a grace period) - Fixed linking against intermediate dependencies in their build folder instead of the final build output file - [issue #921][issue921], [pull #922][issue922] - Fixed omission of packages in a moderately complex sub package scenario - [issue #923][issue923], [pull #924][issue924] - Fixed the default lib command line flag passed to LDC when building shared libraries (by Олег Леленков aka goodbin) - [pull #930][issue930] - Fixed extraneous fields getting added to the package recipe by "dub convert" - [issue #820][issue820], [pull #901][issue901] [issue820]: https://github.com/dlang/dub/issues/820 [issue879]: https://github.com/dlang/dub/issues/879 [issue883]: https://github.com/dlang/dub/issues/883 [issue884]: https://github.com/dlang/dub/issues/884 [issue887]: https://github.com/dlang/dub/issues/887 [issue888]: https://github.com/dlang/dub/issues/888 [issue891]: https://github.com/dlang/dub/issues/891 [issue895]: https://github.com/dlang/dub/issues/895 [issue896]: https://github.com/dlang/dub/issues/896 [issue897]: https://github.com/dlang/dub/issues/897 [issue901]: https://github.com/dlang/dub/issues/901 [issue918]: https://github.com/dlang/dub/issues/918 [issue921]: https://github.com/dlang/dub/issues/921 [issue922]: https://github.com/dlang/dub/issues/922 [issue923]: https://github.com/dlang/dub/issues/923 [issue924]: https://github.com/dlang/dub/issues/924 [issue930]: https://github.com/dlang/dub/issues/930 [issue932]: https://github.com/dlang/dub/issues/932 [issue933]: https://github.com/dlang/dub/issues/933 v1.0.0 - 2016-06-20 ------------------- ### Features and improvements ### - Implemented support for single-file packages, including shebang script support - [issue #103][issue103], [pull #851][issue851], [pull #866][issue866], [pull #870][issue870], [pull #878][issue878] - Builds on DMD 2.065.0 up to 2.071.1 - Removed all deprecated functionality from the API, CLI and data formats - The minimum supported OS X version is now 10.7 - Switched from `std.stream` to `std.stdio` (beware that a recent version of DMD is now necessary when building DUB to support Unicode file names on Windows) - [pull #847][issue847] - Now passes `-vcolumns` also to LDC - [issue #859][issue859], [pull #860][issue860] ### Bug fixes ### - Avoids superfluous registry queries when building - [issue #831][issue831], [pull #861][issue861] - Fixed handling of "libs" on Windows/DMD when building in `allAtOnce` mode - Fixed building with LDC on Windows for both, the VisualStudio based version and the MinGW version - [issue #618][issue618], [pull #688][issue688] - Fixed escaping of command line arguments with spaces for LDC - [issue #834][issue834], [pull #860][issue860] [issue103]: https://github.com/dlang/dub/issues/103 [issue618]: https://github.com/dlang/dub/issues/618 [issue688]: https://github.com/dlang/dub/issues/688 [issue831]: https://github.com/dlang/dub/issues/831 [issue834]: https://github.com/dlang/dub/issues/834 [issue847]: https://github.com/dlang/dub/issues/847 [issue851]: https://github.com/dlang/dub/issues/851 [issue859]: https://github.com/dlang/dub/issues/859 [issue860]: https://github.com/dlang/dub/issues/860 [issue861]: https://github.com/dlang/dub/issues/861 [issue866]: https://github.com/dlang/dub/issues/866 [issue870]: https://github.com/dlang/dub/issues/870 [issue878]: https://github.com/dlang/dub/issues/878 v0.9.25 - 2016-05-22 -------------------- ### Features and improvements ### - Builds on DMD 2.064.2 up to 2.071.0 - Cleaned up the API to be (almost) ready for the 1.0.0 release - [issue #349][issue349] - [pull #785][issue785] - Implemented new semantics for optional dependencies (now controlled using dub.selections.json) - [issue #361][issue361], [pull #733][issue733] - Made "dub init" interactive to improve/simplify the creation of new packages (can be disabled with the "-n" switch) - [pull #734][issue734] - Switched back the default "dub init" recipe format to JSON (both, JSON and SDLang will stay supported) - [issue #724][issue724] - Locally cached packages are now stored in a folder that matches their name, which enables more possible ways to organize the source code (mostly by Guillaume Piolat aka p0nce) - [issue #502][issue502], [pull #735][issue735] - Improved worst-case speed of the dependency resolver for some pathological cases - Sped up GIT based local package version detection using a cache on Windows - [pull #692][issue692] - Implemented "dub convert" to convert between JSON and SDLang package recipes - [pull #732][issue732] - Implemented a "dub search" command to search the package registry from the CLI - [pull #663][issue663] - "dub test" doesn't build dependencies in unittest mode anymore - [issue #640][issue640], [issue #823][issue823] - Added a "-ddoxTool"/"x:ddoxTool" field to override the package used for DDOX documentation builds - [pull #702][issue702] - DUB init now uses the users full name on Posix systems - [issue #715][issue715] - Added support for the "DFLAGS" environment variable to "dub test" - Added a "release-debug" default build type - Path based dependencies are now also stored in dub.selections.json - [issue #772][issue772] - Entries in dub.selections.json are now output in alphabetic order - [issue #709][issue709] - The Sublime Text generator now outputs import paths for use with DKit (by xentec) - [pull #757][issue757] - The VisualD generator now creates the project files in the ".dub" subdirectory (by Guillaume Piolat aka p0nce) - [pull #680][issue680] ### Bug fixes ### - Fixed outputting global build settings (e.g. architecture flags) only once - [issue #346][issue346], [issue #635][issue635], [issue #686][issue686], [pull #759][issue759] - Fixed an infinite recursive DUB invocation if dub was invoked in "preGenerateCommands" (by Nick Sabalausky) - [issue #616][issue616], [pull #633][issue633] - Fixed the VisualD generator to set the correct debug working directory - Fixed disabling bounds-checking on LDC to avoid the deprecated/removed `-noboundscheck` flag (by Guillaume Piolat aka p0nce) - [pull #693][issue693] - Fixed race conditions when running multiple DUB instances concurrently - [issue #674][issue674], [pull #683][issue683] - Fixed the error message when trying to build with DUB from a directory that doesn't contain a package - [issue #696][issue696] - Fixed running the pre-compiled version of DUB on Mac OS versions prior to 10.11 (by Guillaume Piolat aka p0nce) - [pull #704][issue704] - Fixed "dub dustmite" to emit a proper DUB command line if no explicit compiler/architecture is given - Fixed "dub dustmite" when invoked on packages with path based dependencies - [issue #240][issue240], [pull #762][issue762] - Fixed target type inheritance from the top level scope in the SDLang recipe parser - Fixed the error message when a dependency name is omitted in an SDLang recipe (by lablanu) - [pull #723][issue723] - Fixed the error message when using one of the "list" modes of "dub describe" on a target type "none" package - [issue #739][issue739] - Fixed writing the "subConfigurations" field in the JSON recipe of downloaded packages - [issue #745][issue745] - Fixed recently updated packages sometimes to fail to download - [issue #528][issue528] - Fixed handling of path based dependencies that have internal sub package references - [issue #754][issue754], [pull #766][issue766] - Fixed issues with generated CMake files due to backslashes in paths on Windows (by Steven Dwy) - [pull #738][issue738] - Fixed path based dependencies sometimes overriding version based dependencies of the same package - [issue #777][issue777] - Fixed loading of packages that have a path based selection - Fixed detection of compiler errors in the build output for generated Sublime Text projects (by Justinas Šneideris aka develop32) - [pull #788][issue788] - Fixed handling of certain libraries that got included using "pkg-config" (by Jean-Baptiste Lab) - [issue #782][issue782], [pull #794][issue794] - Quick fix for building shared libraries with LDC/Windows/OS X and DMD/OS X (by Guillaume Piolat aka p0nce) - [pull #801][issue801] - Fixed several issues with the SDLang parser - Fixed release-specific regressions regarding sub package dependencies that got ignored during dependency graph collection - [issue #803][issue803], [pull #807][issue807] - Fixed target type "none" packages still generating a binary target (affected `dub describe`) - Fixed `dub describe --data-list target-type` work for target type "none" packages [issue240]: https://github.com/dlang/dub/issues/240 [issue346]: https://github.com/dlang/dub/issues/346 [issue349]: https://github.com/dlang/dub/issues/349 [issue361]: https://github.com/dlang/dub/issues/361 [issue502]: https://github.com/dlang/dub/issues/502 [issue528]: https://github.com/dlang/dub/issues/528 [issue616]: https://github.com/dlang/dub/issues/616 [issue633]: https://github.com/dlang/dub/issues/633 [issue635]: https://github.com/dlang/dub/issues/635 [issue640]: https://github.com/dlang/dub/issues/640 [issue663]: https://github.com/dlang/dub/issues/663 [issue674]: https://github.com/dlang/dub/issues/674 [issue680]: https://github.com/dlang/dub/issues/680 [issue683]: https://github.com/dlang/dub/issues/683 [issue686]: https://github.com/dlang/dub/issues/686 [issue692]: https://github.com/dlang/dub/issues/692 [issue693]: https://github.com/dlang/dub/issues/693 [issue696]: https://github.com/dlang/dub/issues/696 [issue702]: https://github.com/dlang/dub/issues/702 [issue704]: https://github.com/dlang/dub/issues/704 [issue709]: https://github.com/dlang/dub/issues/709 [issue715]: https://github.com/dlang/dub/issues/715 [issue723]: https://github.com/dlang/dub/issues/723 [issue724]: https://github.com/dlang/dub/issues/724 [issue732]: https://github.com/dlang/dub/issues/732 [issue733]: https://github.com/dlang/dub/issues/733 [issue734]: https://github.com/dlang/dub/issues/734 [issue735]: https://github.com/dlang/dub/issues/735 [issue738]: https://github.com/dlang/dub/issues/738 [issue739]: https://github.com/dlang/dub/issues/739 [issue745]: https://github.com/dlang/dub/issues/745 [issue754]: https://github.com/dlang/dub/issues/754 [issue757]: https://github.com/dlang/dub/issues/757 [issue759]: https://github.com/dlang/dub/issues/759 [issue762]: https://github.com/dlang/dub/issues/762 [issue766]: https://github.com/dlang/dub/issues/766 [issue772]: https://github.com/dlang/dub/issues/772 [issue777]: https://github.com/dlang/dub/issues/777 [issue782]: https://github.com/dlang/dub/issues/782 [issue785]: https://github.com/dlang/dub/issues/785 [issue788]: https://github.com/dlang/dub/issues/788 [issue794]: https://github.com/dlang/dub/issues/794 [issue801]: https://github.com/dlang/dub/issues/801 [issue803]: https://github.com/dlang/dub/issues/803 [issue807]: https://github.com/dlang/dub/issues/807 [issue823]: https://github.com/dlang/dub/issues/823 v0.9.24 - 2015-09-20 -------------------- ### Features and improvements ### - Added support for [SDLang][sdl-package-format] based package descriptions - [issue #348][issue348], [pull #582][issue582] - Source code updated to build with DMD 2.064.2 through 2.068.0 - Enhanced `dub describe` support: - The D API is now strongly typed instead of using `Json` - Added a `"targets"` field that can be used to sport external build tools - Added a `--data=X` switch to get information in a shell script friendly format (by Nick Sabalausky) - [pull #572][issue572] - Added an `"active"` field to each package to be used to signal if a certain dependency takes part in the build - [issue #393][issue393] - Added a set of additional environment variables that are available to pre/post build/generate commands (by Nick Sabalausky) - [issue #593][issue593] - Errors and warnings are not suppressed anymore, but output to stderr - Added the possibility to get all import paths for `dub describe` (by w0rp) - [pull #552][issue552], [issue #560][issue560], [pull #561][issue561] - Added stricter package name validation checks - Added a `--bare` option to search for dependencies only in the current directory (useful for running tests) - Removed the deprecated "visuald-combined" generator (use `dub generate visuald --combined` instead) - The command line shown for verbose output now contain the same quotes as used for the actual command invocation - Uses `-vcolumns` for DMD if supported - [issue #581][issue581] - Properly suppressing compiler output when `--quiet` or `--vquiet` are given (by Nick Sabalausky) - [issue #585][issue585], [pull #587][issue587] - Added a warning when referencing sub packages by their path (instead of their parent's path) - Building `sourceLibrary` targets with `-o-` is allowed now (enables documentation generation in particular) - [issue #553][issue553] - The VisualD generator doesn't use a "_d" suffix for debug build targets anymore (by Guillaume Piolat aka p0nce) - [pull #617][issue617] - Added a new "profile-gc" build type - Cleaned up console output (parts by Guillaume Piolat aka p0nce) - [pull #621][issue621] - Added "arm" and "arm_thumb" cross-compilation invocation support for GDC - Added configuration support to set the default compiler binary "defaultCompiler" field in the settings.json file - Removed the build script based selection of the default compiler (by Marc Schütz) - [pull #678][issue678] - Added a `--skip-registry=` switch to skip searching for packages on remote registries - [issue #580][issue580] ### Bug fixes ### - Fixed quoting of command line arguments for the DMD backend in the linker phase - [issue #540][issue540] - Fixed running Dustmite with versioned dependencies that are available as a git working copy - Fixed dependency resolution for packages that have sub packages and all of them are path based - [issue #543][issue543] - Fixed the error message for path based dependencies that are missing a package description file - see [issue #535][issue535] - Fixed running Dustmite with dub not available in `PATH` - [pull #547][issue547] - Fixed passing compiler, architecture, build type and configuration options to Dustmite - [pull #547][issue547] - Fixed return code when `dub run` is used on a library (returns non-zero now) - [pull #546][issue546] - Fixed spurious warning when building a package by name and DUB is not run from a package directory - Fixed handling of dependency errors that occur during automatic upgrade checks - [issue #564][issue564], [pull #565][issue565] - Fixed the architecture flag for x64 passed to LDC (by p0nce) - [pull #574][issue574] - Fixed enforcement of build requirements in dependencies - [issue #592][issue592] - Fixed `dub remove` to only remove managed packages - [issue #596][issue596] - Added a workaround for a data corruption issue (codegen bug) - [issue #601][issue601] - Fixed building dynamic libraries with DMD - [issue #613][issue613] [sdl-package-format]: http://code.dlang.org/package-format?lang=sdl [issue348]: https://github.com/dlang/dub/issues/348 [issue393]: https://github.com/dlang/dub/issues/393 [issue535]: https://github.com/dlang/dub/issues/535 [issue540]: https://github.com/dlang/dub/issues/540 [issue543]: https://github.com/dlang/dub/issues/543 [issue546]: https://github.com/dlang/dub/issues/546 [issue547]: https://github.com/dlang/dub/issues/547 [issue552]: https://github.com/dlang/dub/issues/552 [issue552]: https://github.com/dlang/dub/issues/552 [issue553]: https://github.com/dlang/dub/issues/553 [issue560]: https://github.com/dlang/dub/issues/560 [issue561]: https://github.com/dlang/dub/issues/561 [issue564]: https://github.com/dlang/dub/issues/564 [issue565]: https://github.com/dlang/dub/issues/565 [issue572]: https://github.com/dlang/dub/issues/572 [issue574]: https://github.com/dlang/dub/issues/574 [issue580]: https://github.com/dlang/dub/issues/580 [issue581]: https://github.com/dlang/dub/issues/581 [issue582]: https://github.com/dlang/dub/issues/582 [issue585]: https://github.com/dlang/dub/issues/585 [issue587]: https://github.com/dlang/dub/issues/587 [issue592]: https://github.com/dlang/dub/issues/592 [issue593]: https://github.com/dlang/dub/issues/593 [issue596]: https://github.com/dlang/dub/issues/596 [issue601]: https://github.com/dlang/dub/issues/601 [issue613]: https://github.com/dlang/dub/issues/613 [issue617]: https://github.com/dlang/dub/issues/617 [issue621]: https://github.com/dlang/dub/issues/621 [issue678]: https://github.com/dlang/dub/issues/678 v0.9.23 - 2015-04-06 -------------------- ### Features and improvements ### - Compiles with DMD frontend versions 2.064 up to 2.067 - Largely reduced the execution time needed by DUB itself during builds - [pull #388][issue388] - Added a `dub clean-caches` command to clear online registry meta data that is cached locally - [pull #433][issue433] - Added a "deimos" template type to the `dub init` command - [pull #431][issue431] - Added support for dub init to take a list of dependencies (by Colin Grogan) - [pull #453][issue453] - Example: `dub init myProj logger vibe-d gfm --type=vibe.d` - DUB will try to get the latest version number for each of these dependencies from [code.dlang.org](http://code.dlang.org/) and automatically add them to the dependencies section of dub.json - The previous syntax where the argument to `dub init` is the project type instead of a dependency list is preserved, but deprecated - use the `--type=` switch instead - Added a project generator for Sublime Text (by Nicholas Londey) - [pull #461][issue461] - Added a project generator for CMake files (by Steven Dwy) - [pull #489][issue489] - Added support for `dub test` and modules where the path doesn't match the module name (by Szabo Bogdan) - [pull #344][issue344] - Added `dub --version` option to output the program version and build date - [pull #513][issue513] - Improved `"copyFiles"` support - Added support for glob matches (by Colden Cullen) - [pull #407][issue407] - Added support for copying directories (by Vadim Lopatin) - [pull #471][issue471] - Files are now hard linked into the target directory instead of making a real copy - Avoids to hard link `"copyFiles"` that have not changed in the source directory on Windows - [issue #511][issue511] - DUB now searches the PATH for installed compilers and chooses the default compiler as appropriate - [issue #480][issue480], [pull #506][issue506] - `--build-mode=singleFile` can now build several files in parallel using the `--parallel` switch - [issue #498][issue498] - Improved the JSON error diagnostic format to `file(line): Error: message` for better IDE integration - [issue #317][issue317] ### Bug fixes ### - Fixed determining module names from empty modules for `dub test` (by Szabo Bogdan) - [pull #458][issue458] - Fixed generating VisualStudio solution files on Win64 (by Nicholas Londey) - [pull #455][issue455] - Fixed erroneously adding "executable" dependencies to the list of link dependencies (by Михаил Страшун aka Dicebot) - [pull #474][issue474] - Fixed overriding the default source paths with `"sourcePaths"` - [issue #483][issue483] - Fixed removing packages when build output files exist - [issue #377][issue377] - Fixed handling of sub package references that specify an explicit path - [issue #448][issue448] - Fixed erroneous detection of a "sourcemain.d" source file under certain circumstances - [issue #487][issue487] - Fixed `dub build -t ddox` on OS X - [issue #354][issue354] - Fixed using unique temporary files (by Михаил Страшун aka Dicebot) - [issue #482][issue482], [pull #497][issue497] - Fixed compiler command line issues on Windows with `--buildMode=singleFile` (by machindertech) - [pull #505][issue505] - Fixed a version range match error (">=A _PACKAGE_DIR` variables - Generalized the `--local`/`--system` flags to `--cache=`, which is now available for all commands (by Colden Cullen) - [pull #306][issue306] - Added a `--build-mode` switch to choose between combined build and separate compile/link for DMD - When building a static library, its dependencies are not built anymore - [issue #316][issue316] - Displaying the line number where parsing a JSON document fails - see [issue #317][issue317] - Added a shorthand syntax for sub packages (":subpack" instead of "parent:subpack") - [issue #315][issue315] - Replace all "package.json" files/mentions with "dub.json" and clean up white space throughout the code base (by James Clarke aka jrtc27) - [pull #337][issue337], [pull #338][issue338], [pull #339][issue339] - `dub describe` not outputs all source/import files of all configurations and platforms - [issue #185][issue185] - Added basic support for the new human readable `"systemDependencies"` field - Added a `--temp-build` switch to force building in a temporary folder - [issue #294][issue294] - Using `executeShell` when invoking tools to enable more flexible use of shell features - [issue #356][issue356] - `dub init` now creates a default `.gitignore` file - An exit code of `-9` for a tool now triggers a short message with a possible cause (out of memory) - The information about possible package upgrades is now cached for one day, resulting in less online queries to the package registry - Implemented separate compile/link mode for GDC (by Mathias Lang aka Geod24) - [pull #367][issue367] - `.def` files are now passed to the linking stage when doing separate compile/link building - Added BASH shell completion script (by Per Nordlöw) - [issue #154][issue154] - Added FISH shell completion script (by Matt Soucy) - [pull #375][issue375] ### Bug fixes ### - Fixed automatic removing of packages, removing was only possible with --force-remove. - Fixed "local" package fetching (was doing the same as "system") - [issue #259][issue259] - Fixed handling of `"mainSourceFile"` when building with `--rdmd` - [issue #263][issue263] - Fixed useless separate compilation of dependencies when building with `--rdmd` - see [issue #255][issue255] - Fixed detection of known files during package removal, caused by a missing ending slash (by Matthias Dondorff) - Fixed `dub fetch --version=` to actually fetch the supplied version (by Matthias Dondorff) - Fixed linker issues for GCC based linking by putting `-l` flags after the list of source files - [issue #281][issue281] - Fixed spurious log output happening during `dub describe` - [issue #221][issue221] - Fixed interrupting the DDOX process for `dub -b ddox` (by Martin Nowak) - [pull #291][issue291] - Fixed building library targets with LDC (by Dmitri Makarov) - [pull #296][issue296] - Fixed the `"disallowInlining"` build option (by sinkuu) - [pull #297][issue297] - Fixed determining build flags using pkg-config when some libraries are unknown to pkg-config - [issue #274][issue274] - Fixed detection of dependency cycles - [issue #280][issue280] - Fixed detection of a required rebuild when the compiler (front end) version changes - [issue #284][issue284] - Fixed building of packages with a non-existent `"targetPath"` - [issue #261][issue261] - Fixed the warning that should appear when using manual `-debug=` flags instead of `"debugVersions"` - [issue #310][issue310] - Fixed processing of variables in `"preGenerateCommands"` and `"postGenerateCommands"` - Fixed handling of empty path nodes (e.g. "/home//someone/somefile") - [issue #177][issue177] - Fixed the up-to-date check for intermediate dependencies - Fixed detection of equal paths for `dub add-local` when only the ending slash character differs - [issue #268][issue268] - Fixed a bogus warning that the license of a sub package differs from the parent package when the sub package doesn't specify a license - Fixed building when files from "\\UNC" paths are involved - [issue #302][issue302] - Fixed up-to-date checking for embedded sub packages (by sinkuu) - [pull #336][issue336] - Fixed outputting multiple instances of the same platform flag which broke the build for some compilers - [issue #346][issue346] - Fixed referencing path based sub packages - [issue #347][issue347] - Fixed various error messages (by p0nce and sinkuu) - [pull #368][issue368], [pull #376][issue376] - Fixed the "ddox" build mode when DDOX hasn't already been installed - [issue #366][issue366] - Fixed probing the compiler for platform identifiers when performing cross compiling (by Mathias Lang aka Geod24) - [pull #380][issue380] - Fixed erroneously dropping the `"buildTypes"` field of downloaded packages (by sinkuu) - [pull #406][issue406] - Fixed trying to copy files with the same source and destination - Fixed downloading of packages with "+" in their version - [issue #411][issue411] - Fixed building dependencies with versions containing "+" on Windows/OPTLINK - Fixed a crash when sub packages of non-installed base packages are references - [issue #398][issue398] - Fixed repeated download of base packages when a non-existent sub package is referenced - Fixed intermediate build path for `--compiler=` binaries specified with path separators - [issue #412][issue412] [issue134]: https://github.com/rejectedsoftware/dub/issues/134 [issue144]: https://github.com/rejectedsoftware/dub/issues/144 [issue154]: https://github.com/rejectedsoftware/dub/issues/154 [issue177]: https://github.com/rejectedsoftware/dub/issues/177 [issue185]: https://github.com/rejectedsoftware/dub/issues/185 [issue221]: https://github.com/rejectedsoftware/dub/issues/221 [issue255]: https://github.com/rejectedsoftware/dub/issues/255 [issue259]: https://github.com/rejectedsoftware/dub/issues/259 [issue261]: https://github.com/rejectedsoftware/dub/issues/261 [issue263]: https://github.com/rejectedsoftware/dub/issues/263 [issue268]: https://github.com/rejectedsoftware/dub/issues/268 [issue271]: https://github.com/rejectedsoftware/dub/issues/271 [issue274]: https://github.com/rejectedsoftware/dub/issues/274 [issue280]: https://github.com/rejectedsoftware/dub/issues/280 [issue281]: https://github.com/rejectedsoftware/dub/issues/281 [issue283]: https://github.com/rejectedsoftware/dub/issues/283 [issue284]: https://github.com/rejectedsoftware/dub/issues/284 [issue291]: https://github.com/rejectedsoftware/dub/issues/291 [issue294]: https://github.com/rejectedsoftware/dub/issues/294 [issue296]: https://github.com/rejectedsoftware/dub/issues/296 [issue297]: https://github.com/rejectedsoftware/dub/issues/297 [issue302]: https://github.com/rejectedsoftware/dub/issues/302 [issue303]: https://github.com/rejectedsoftware/dub/issues/303 [issue306]: https://github.com/rejectedsoftware/dub/issues/306 [issue310]: https://github.com/rejectedsoftware/dub/issues/310 [issue313]: https://github.com/rejectedsoftware/dub/issues/313 [issue315]: https://github.com/rejectedsoftware/dub/issues/315 [issue316]: https://github.com/rejectedsoftware/dub/issues/316 [issue317]: https://github.com/rejectedsoftware/dub/issues/317 [issue324]: https://github.com/rejectedsoftware/dub/issues/324 [issue336]: https://github.com/rejectedsoftware/dub/issues/336 [issue337]: https://github.com/rejectedsoftware/dub/issues/337 [issue338]: https://github.com/rejectedsoftware/dub/issues/338 [issue339]: https://github.com/rejectedsoftware/dub/issues/339 [issue346]: https://github.com/rejectedsoftware/dub/issues/346 [issue347]: https://github.com/rejectedsoftware/dub/issues/347 [issue356]: https://github.com/rejectedsoftware/dub/issues/356 [issue364]: https://github.com/rejectedsoftware/dub/issues/364 [issue366]: https://github.com/rejectedsoftware/dub/issues/366 [issue367]: https://github.com/rejectedsoftware/dub/issues/367 [issue368]: https://github.com/rejectedsoftware/dub/issues/368 [issue375]: https://github.com/rejectedsoftware/dub/issues/375 [issue376]: https://github.com/rejectedsoftware/dub/issues/376 [issue380]: https://github.com/rejectedsoftware/dub/issues/380 [issue398]: https://github.com/rejectedsoftware/dub/issues/398 [issue406]: https://github.com/rejectedsoftware/dub/issues/406 [issue411]: https://github.com/rejectedsoftware/dub/issues/411 [issue412]: https://github.com/rejectedsoftware/dub/issues/412 v0.9.21 - 2014-02-22 -------------------- ### Features and improvements ### - Implemented building dependencies as separate libraries (use `--combined` to use - almost - the old behavior) - The preferred package description file name is now "dub.json" instead of "package.json" (which is still supported) - Revamped command line help now shows detailed help for each command - Added `dub test` to run the unit tests of a package using a custom main() function - Public sub packages can now (and are recommended to) reside in sub folders - Added ruby style `~>` version specifications: `"~>1.0.2"` is equivalent to `">=1.0.2 <1.1.0"` and `"~>1.3"` is equivalent to `">=1.3.0 <2.0.0"` - `--annotate` now works for all commands - Added a `--force-remove` switch to force package removal when untracked files are found in a package folder - Added a `"mainSourceFile"` field to better control how `--rdmd` and `dub test` work - The target binary (if any) is now automatically deleted after a linker error to avoid partially linked binaries - Added `--force` to `dub build` and `dub run` to force recompilation even if already up to date - Renamed the "debug_" and "release" build options to "debugMode" and "releaseMode" to avoid the D keyword clash - Renamed the "noBoundsChecks" build option to "noBoundsCheck" to be consistent with the corresponding build requirement - `dub init xxx vibe.d` now emits a `-version=VibeDefaultMain` as required by the latest versions - Reimplemented the VisualD project generator to use the new compile target logic - Instead of `dub generate visuald-combined` use `dub generate visuald --combined` - Properly handles the explicit library target types (those other than `"targetType": "library"`) - Added support for `dub add-local` without an explicit version argument (will be inferred using GIT) (by p0nce) - [pull #194][issue194] - Added a new "release-nobounds" build type - Improved the error message when "dub remove" fails because of a missing installation journal - Removed the Mono-D project generator - use Mono-D's built in DUB support instead - Added support for public sub packages in sub folders - this is the preferred way to use sub packages, see - Only "main.d"/"app.d" or "packname/main.d"/"packname/app.d" are now automatically treated as `"mainSourceFile"` for executable targets and none for library targets - Excessive/unknown command line arguments now result in an error - The "checking dependencies" message on startup is now a diagnostic message - A `"dflags"` entry of the form `-defaultlib=*` for DMD is now passed to the linking stage for separate compilation - Added simple support for `--arch=x86` and `--arch=x86_64` and LDC - The order of source files as passed to the compiler is now sorted by name to avoid random triggering of order dependent compiler issues ### Bug fixes ### - Fixed a malformed log message for files with modification times in the future - Fixed handling of absolute working directories - Fixed a segmentation fault on OS X when doing `dub upgrade` - [issue #179][issue179] - Fixed extraction of pre-release SemVer versions from the "git describe" output - Fixed handling of paths with spaces in generated VisualD projects - Fixed DUB binaries compiled with GDC/LDC to work around a crash issue in `std.net.curl` - [issue #109][issue109], [issue #135][issue135] - Fixed iterating over directories containing invalid symbols links (e.g. when searching a directory for packages) - Fixed the path separators used for `$DUBPATH` (':' on Posix and ';' on Windows) - Fixed using custom registries in the global DUB configuration file - [issue #186][issue186] - Fixed assertions triggering when `$HOME` is a relative path (by Ognjen Ivkovic) - [pull #192][issue192] - Fixed the VisualD project generator to enforce build requirements - Fixed build requirements to also affect compiler options of the selected build - Fixed configuration resolution for complex dependency graphs (it could happen that configurations were picked that can't work on the selected platform) - Fixed `dub build -b ddox` to only copy resource files from DDOX if they are newer than existing files on Posix - Fixed storing sub packages when the modified package description is written after fetching a package - Fixed a bogus "conflicting references" error when referencing sub packages [issue #214][issue214] - Fixed a null pointer dereference for locally registered package directories that had been deleted - Fixed determining the version of the root package (previously, `~master` was always assumed) - Fixed parsing of `==~master` style dependencies (equivalent to just `~master`) - Fixed handling of packages with upper case letters in their name (which is not allowed) - Fixed running applications on Windows with relative paths (`.\` gets prepended now) [issue109]: https://github.com/rejectedsoftware/dub/issues/109 [issue135]: https://github.com/rejectedsoftware/dub/issues/135 [issue179]: https://github.com/rejectedsoftware/dub/issues/179 [issue186]: https://github.com/rejectedsoftware/dub/issues/186 [issue192]: https://github.com/rejectedsoftware/dub/issues/192 [issue194]: https://github.com/rejectedsoftware/dub/issues/194 [issue214]: https://github.com/rejectedsoftware/dub/issues/214 v0.9.20 - 2013-11-29 -------------------- ### Features and improvements ### - Compiles on DMD 2.064 without warnings - [issue #116][issue116] - Builds are cached now by default in the ".dub/" sub folder of each package - An explicit "dub upgrade --prerelease" is now necessary to upgrade to pre-release versions of dependencies - "dub describe" and generated VisualD projects now also contain pure import and string import files - "dub run" now only builds in "/tmp" or "%TEMP%" if the package folder is write protected - [issue #82][issue82] - "dub init" can not take an optional project template name (currently "minimal" or "vibe.d") - Renamed "dub install" to "dub fetch" to avoid giving the impression of actual system installation (by Михаил Страшун aka Dicebot) - [pull #150][issue150] - Added support for "dub describe (package name)" and "dub describe --root=(path to package)" to describe packages outside of the CWD - `"excludedSourceFiles"` now supports [glob expressions](http://dlang.org/phobos/std_path.html#.globMatch) (by Jacob Carlborg) - [pull #155][issue155] - "dub --build=ddox" now starts a local HTTP server and automatically opens the browser to display the documentation - Environment variables can now be used inside path based fields in package.json (by Alexei Bykov) - [pull #158][issue158] - "dub describe" now contains a `"targetFileName"` field that includes the file extension (e.g. ".exe" or ".so") - Removed the compatibility version of the new `std.process` as it lacks support for `browse()` - Support using .obj/.lib/.res/.o/.a/.so/.dylib files to be specified as "sourceFiles", they will be bassed to the compiler at the linking stage - Added a "library-nonet" configuration to the package description file to compile without a CURL dependency - Added support for the "http_proxy" environment variable ### Bug fixes ### - Fixed building of explicitly selected packages with custom configurations (using "dub build (package name)") - Fixed running DUB from outside of a valid package directory when an explicit package name is given - Fixed dependency calculation for dependencies referenced in configuration blocks - [issue #137][issue137] - Fixed warnings to be enabled as errors by default again - Fixed resolution of dependencies when sub packages are involved - [issue #140][issue140] - Fixed handling of build options for GDC/LDC (by finalpatch) - [pull #143][issue143] - Fixed emitting "-shared -fPIC" for DMD when building shared libraries - [issue #138][issue138] - Fixed "dub --build=ddox" for target types other than "executable" - [issue #142][issue142] - Fixed a crash when loading the main package failed - [issue #145][issue145] - Fixed the error message for empty path strings in the `"sourcePaths"` field - see [issue #149][issue149] - Fixed representing empty relative paths by "." instead of an empty string - [issue #153][issue153] - Fixed running executables for projects outside of the CWD - Fixed copying of DDOX resources on Posix for "--build=ddox" (by Martin Nowak) - [pull #162][issue162] - Fixed ARM floating-point platform/version identifiers - Fixed generating VisualD projects for shared library packages (by p0nce) - [pull #173][issue173] - Fixed erroneous upgrading of packages that are not managed by DUB (for "dub upgrade") - [issue #171][issue171] - Fixed erroneously fetching the same package multiple times when sub packages are used - Fixed string representation of empty paths (fixes the target file name for generated VisualD projects) [issue82]: https://github.com/rejectedsoftware/dub/issues/82 [issue116]: https://github.com/rejectedsoftware/dub/issues/116 [issue137]: https://github.com/rejectedsoftware/dub/issues/137 [issue140]: https://github.com/rejectedsoftware/dub/issues/140 [issue142]: https://github.com/rejectedsoftware/dub/issues/142 [issue143]: https://github.com/rejectedsoftware/dub/issues/143 [issue145]: https://github.com/rejectedsoftware/dub/issues/145 [issue149]: https://github.com/rejectedsoftware/dub/issues/149 [issue150]: https://github.com/rejectedsoftware/dub/issues/150 [issue153]: https://github.com/rejectedsoftware/dub/issues/153 [issue155]: https://github.com/rejectedsoftware/dub/issues/155 [issue158]: https://github.com/rejectedsoftware/dub/issues/158 [issue162]: https://github.com/rejectedsoftware/dub/issues/162 [issue171]: https://github.com/rejectedsoftware/dub/issues/171 [issue173]: https://github.com/rejectedsoftware/dub/issues/173 v0.9.19 - 2013-10-18 -------------------- ### Features and improvements ### - Added the possibility to build or run a specific package, including sub packages - Implemented a new "--root=PATH" switch to let dub operate from a different directory than the current working directory - "dub init" now always emits lower case DUB package names - Improved diagnostic output for "dub add-local" and "dub remove-local" - Using the static version of Phobos fro building DUB to improve platform independence on Linux ### Bug fixes ### - Fixed erroneous "-debug" switches in non-debug builds - Enabled again a warning when using "-debug=" flags in "dflags" instead of using "debugVersions" - Fixed handling of paths with spaces for "--build=ddox" - Fixed inclusion of multiple instances of the same package.json files in the "visuald-combined" generator (by p0nce) - [pull #124][issue124] - Fixed response file output for LDC - [issue #86][issue86] - Fixed response file output for GDC - [issue #125][issue125] - Partially fixed working in paths with Unicode characters by avoiding `std.stdio.File` - [issue #130][issue130] [issue86]: https://github.com/rejectedsoftware/dub/issues/86 [issue124]: https://github.com/rejectedsoftware/dub/issues/124 [issue125]: https://github.com/rejectedsoftware/dub/issues/125 [issue130]: https://github.com/rejectedsoftware/dub/issues/130 v0.9.18 - 2013-09-11 -------------------- ### Features and improvements ### - Added support for a "buildOptions" field to be able to specify compiler options in an abstract way - Implemented a new configuration resolution algorithm that is able to handle complex dependency graphs - Added support for a "debugVersions" field ("-debug=xyz") - Added support for a "-debug=xyz" command line option to specify additional debug version specifiers - The VisualD project generator doesn't specify redundant compiler flags for features that have dedicated checkboxes anymore - Improved folder structure in generated "visuald-combined" projects (by p0nce) - [pull #110][issue110] ### Bug fixes ### - Fixed handling of packages with no configurations (a global `null` configuration is now assumed in this case) - Fixed building of shared libraries (was missing the "-shared" flag) - Fixed upgrading in conjunction with sub packages (was causing an infinite loop) - [issue #100][issue100] - Fixed build of complex generated VisualD projects by avoiding redundant link dependencies - Fixed upgrading of branch based dependencies - Fixed inheriting of global build settings in configurations - [issue #113][issue113] - Fixed inclusion of entry point files (e.g. "source/app.d") in pure library packages - [issue #105][issue105] [issue100]: https://github.com/rejectedsoftware/dub/issues/100 [issue105]: https://github.com/rejectedsoftware/dub/issues/105 [issue110]: https://github.com/rejectedsoftware/dub/issues/110 [issue113]: https://github.com/rejectedsoftware/dub/issues/113 v0.9.17 - 2013-07-24 -------------------- ### Features and improvements ### - Added support for custom build types using the "buildTypes" field - [issue #78][issue78] - Added support for multiple and custom package registry URLs on the command line and as a configuration field - [issue #22][issue22] - Added support for a "workingDirectory" field to control from which directory the generated executable is run - [issue #84][issue84] - Added a new generator "visuald-combined", which combines the whole dependency tree into a single project - Updated default package registry URL to http://code.dlang.org - The default "unittest" and "unittest-cov" build types now issue the "-debug" flag - Building packages without any "importPaths" entry now issue a warning message ### Bug fixes ### - PARTIAL Fixed building with LDC - [issue #86][issue86] - The version string in the HTTP "User-Agent" field is now formatted according to SemVer - Fixed bogus warnings about "dflags" that are confused with flags that are a prefix of those - Fixed the VisualD generator to use the build settings and dependencies of the selected build configuration - Fixed the VisualD generator to enable the proper command line flags for each build type - Generated VisualD projects don't clean up JSON files on clean/rebuild anymore - Fixed building of packages with sub-packages when the main package is registered to DUB - [issue #87][issue87] - Fixed adhering to the specified global target type for library packages that have no explicit build configurations - [issue #92][issue92] - Fixed building of static libraries which have external library dependencies ("libs") - [issue #91][issue91] - Fixed error message for references to unknown sub-packages - Fixed handling of packages that are referenced multiple times using an explicit path - [issue #98][issue98] [issue22]: https://github.com/rejectedsoftware/dub/issues/22 [issue78]: https://github.com/rejectedsoftware/dub/issues/78 [issue84]: https://github.com/rejectedsoftware/dub/issues/84 [issue86]: https://github.com/rejectedsoftware/dub/issues/86 [issue87]: https://github.com/rejectedsoftware/dub/issues/87 [issue91]: https://github.com/rejectedsoftware/dub/issues/91 [issue92]: https://github.com/rejectedsoftware/dub/issues/92 [issue98]: https://github.com/rejectedsoftware/dub/issues/98 v0.9.16 - 2013-06-29 -------------------- ### Bug fixes ### - Fixed fetching of all recursive dependencies in one go - Fixed handling of paths with spaces when using "dub build" - Fixed upwards inheritance of version identifiers in generated VisualD projects v0.9.15 - 2013-06-19 -------------------- ### Features and improvements ### - Added `"targetType": "none"` for packages which don't contain sources and don't generate a binary output - Added build settings to the "dub describe" output ### Bug fixes ### - Fixed fetching of "main:sub" style dependencies from the registry - Remove half-broken support for sub-packages defined in sub-directories (needs to be determined if this feature is worth the trade-offs) - Fixed bogus re-installations of packages referenced by a sub-package - Fixed handling of dependencies of header-only (or target type "none") dependencies in the VisualD generator - Fixed the reported version of sub-packages in the output of "dub describe" v0.9.14 - 2013-06-18 -------------------- ### Features and improvements ### - Implemented support for multiple packages per directory and accessing sub-packages as dependencies - [issue #67][issue67] - Dependencies can now be specified per-configuration in addition to globally - Version numbers are now handled according to [SemVer](http://semver.org/) ("~master" style branch specifiers are independent of this and work as before) - Library packages are now only built when running "dub" instead of trying to execute them - partially [pull #66][issue66] by Vadim Lopatin and [issue #53][issue53] - Add support for optional dependencies (picked up only if already installed) - [issue #5][issue5] - Compiles on DMD 2.063 - The build script now directly calls the compiler instead of relying an rdmd and supports ldmd and gdmd in addition to dmd (automatically detected) - Outputs a warning for package names with upper-case letters and treats package names case insensitive - Added `"buildRequirements": ["noDefaultFlags"]` for testing manual sets of command line flags - [issue #68][issue68] - Errors and diagnostic messages are now written to `stderr` instead of `stdout` - Added "dub describe" to output a build description of the whole dependency tree for external tools given a configuration/compiler/platform combination - Removed the -property switch and deprecated `"buildRequirements": ["relaxProperties"]` - Added support for a `DUBPATH` environment variable and support for adding a directory with multiple packages using "dub add-local" to search for dependencies in local directories other than the predefined ones - Replaced --list-locals/--list-user/--list-system with a single --list-installed switch - The version of DUB is now inferred using "git describe" and output on the help screen and in the user agent string of HTTP requests - Added some minimal example projects for several use cases - Temporarily disabled automatic package upgrading (was only working for the now removed project locally installed packages) ### Bug fixes ### - Fixed recursive inferring of configurations - Fixed including debug information for separate compile/link builds - Fixed VisualD generator for x64 builds and avoid building header-only dependencies - Fixed handling of "-Wl" flags returned by pkg-config - Fixed LDC builds for projects with multiple modules of the same name (but in different packages) using the -oq switch - Fixed the linker workaround in the build script to work on non-Ubuntu systems - [issue #71][issue71] - Fixed handling of Windows UNC paths (by Lutger Blijdestijn) - [pull #75][issue75] - Fixed a possible infinite update loop - [issue #72][issue72] - Fixed handling of multiple compiler/linker arguments with the same content (e.g. "--framework A --framework B" on OS X) [issue5]: https://github.com/rejectedsoftware/dub/issues/5 [issue53]: https://github.com/rejectedsoftware/dub/issues/53 [issue66]: https://github.com/rejectedsoftware/dub/issues/66 [issue67]: https://github.com/rejectedsoftware/dub/issues/67 [issue68]: https://github.com/rejectedsoftware/dub/issues/68 [issue71]: https://github.com/rejectedsoftware/dub/issues/71 [issue72]: https://github.com/rejectedsoftware/dub/issues/72 [issue75]: https://github.com/rejectedsoftware/dub/issues/75 v0.9.13 - 2013-04-16 -------------------- ### Features and improvements ### - Implemented `"buildRequirements"` to allow packages to specify certain build requirements (e.g. avoiding function inlining or warnings) - Experimental support to specify flags to pass to "ddox filter" for --build=ddox - Configurations inherit the global `"targetType"` by default now - Import paths in VisualD projects are now relative - Cleaner console output for -v (no thread/fiber ID is printed anymore) - Build settings for VisualD projects are tuned to avoid common linker/compiler bugs by default - Generated VisualD projects put intermediate files to ".dub/obj/<projectname>" now ### Bug fixes ### - Fixed upgrading of branch based dependencies - [issue #55][issue55] - Fixed wording and repetition of the reserved compiler flag warning message - [issue #54][issue54] - Fixed erroneous inclusion of .d files in the import libraries field of generated VisualD projects - Fixed passing "package.json" to the compiler in generated Mono-D projects - [issue #60][issue60] - Fixed the Mono-D and VisualD generators to properly copy `"copyFiles"` - [issue #58][issue58] - Fixed removing of temporary files in case of unexpected folder contents - [issue #41][issue41] - Fixed invocation of the linker on Windows in case of another "link.exe" being in PATH - [issue #57][issue57] - Fixed computation of build settings for VisualD projects (inheritance works only bottom to top now) [issue41]: https://github.com/rejectedsoftware/dub/issues/41 [issue54]: https://github.com/rejectedsoftware/dub/issues/54 [issue55]: https://github.com/rejectedsoftware/dub/issues/55 [issue57]: https://github.com/rejectedsoftware/dub/issues/57 [issue58]: https://github.com/rejectedsoftware/dub/issues/58 [issue60]: https://github.com/rejectedsoftware/dub/issues/60 v0.9.12 - 2013-03-21 -------------------- ### Features and improvements ### - Implemented separate compile/link building when using DMD - Optimized platform field matching (by Robert Klotzner) - [pull #47][issue47] - Added build types for coverage analysis - [issue #45][issue45] - Wrong use of `"dflags"` now triggers a warning with suggestion for an alternative approach - [issue #37][issue37] - The "dub" binary is now in "bin/" instead of the root directory ### Bug fixes ### - Fixed an assertion that triggered when appending an absolute path - Fixed `--build=ddox` when DDOX was not yet installed/built - [issue #42][issue42] - Fixed the build script to work on Ubuntu - Fixed building in a project directory that contains no "package.json" file - Fixed the error message for non-existent dependency versions - [issue #44][issue44] - Fixed matching of (only) D source files (by Robert Klotzner) - [pull #46][issue46] - Fixed `"targetName"` and `"targetPath"` fields - [issue #48][issue48] [issue37]: https://github.com/rejectedsoftware/dub/issues/37 [issue42]: https://github.com/rejectedsoftware/dub/issues/42 [issue44]: https://github.com/rejectedsoftware/dub/issues/44 [issue45]: https://github.com/rejectedsoftware/dub/issues/45 [issue46]: https://github.com/rejectedsoftware/dub/issues/46 [issue47]: https://github.com/rejectedsoftware/dub/issues/47 [issue48]: https://github.com/rejectedsoftware/dub/issues/48 v0.9.11 - 2013-03-05 -------------------- ### Features and improvements ### - Configurations are now "shallow", meaning that configurations of dependencies can be selected by a package, but stay invisible to users of the package itself - [issue #33] - Target type selection is now supported (executable, static lib, dynamic lib etc.) - [issue #26][issue26] - Target name and path can be configured now - Added a possibility to exclude certain files from the build - The package description files is now added to IDE projects - [issue #35][issue35] - Using a response file to handle large compiler command lines - [issue #19][issue19] ### Bug fixes ### - Fixed spurious loading of the package during `dub install` - [issue #25][issue25] [issue19]: https://github.com/rejectedsoftware/dub/issues/19 [issue25]: https://github.com/rejectedsoftware/dub/issues/25 [issue26]: https://github.com/rejectedsoftware/dub/issues/26 [issue35]: https://github.com/rejectedsoftware/dub/issues/35 v0.9.10 - 2013-03-04 -------------------- ### Features and improvements ### - Added direct support for generating HTML documentation using DDOC or DDOX - Added support for pre/post generate/build commands - `dub install` does not add a dependency anymore (reverted to old behavior) ### Bug fixes ### - `dub uninstall` actually works now - The Windows installer also installs the needed DLLs - Fixed Windows paths on non-Windows systems emitted by the Mono-D generator - [issue #32][issue32] [issue32]: https://github.com/rejectedsoftware/dub/issues/32 v0.9.9 - 2013-02-28 ------------------- ### Features and improvements ### - Adds a Windows installer (by Brad Anderson aka eco) - [pull #27][issue27] - Support for branches other than "~master" - The MonoD generator now generates a pretty source hierarchy for dependencies - The "sourcePath" field has been changed to "sourcePaths" to support multiple paths (by Nathan M. Swan aka carlor) - [pull #28][issue28] ### Bug fixes ### - "dub init" with no arguments uses the current directory name as the project name - [issue #16][issue16] - The tilde character is not used for path names anymore - [issue #23][issue23] [issue16]: https://github.com/rejectedsoftware/dub/issues/16 [issue23]: https://github.com/rejectedsoftware/dub/issues/23 [issue27]: https://github.com/rejectedsoftware/dub/issues/27 [issue28]: https://github.com/rejectedsoftware/dub/issues/28 dub-1.19.0/CONTRIBUTING.md000066400000000000000000000013141360435400500146040ustar00rootroot00000000000000# Guidelines for Contributing ## Building Build a development version of dub using either `./build.sh` or `./build.cmd` on Windows. When you already have a working dub binary, you can also just run `dub build`, though that won't update the version string. ## Changelog Every feature addition should come with a changelog entry, see the [changelog/README.md](changelog/README.md) for how to add a new entry. Any `.dd` file is rendered using ddoc and is the same format used across all dlang repos. For bugfixes make sure to automatically [close the issue via commit message](https://blog.github.com/2013-01-22-closing-issues-via-commit-messages/) (e.g. `fixes #123`), so that they can be listed in the changelog. dub-1.19.0/Jenkinsfile000066400000000000000000000000601360435400500145340ustar00rootroot00000000000000#!/bin/env groovy library 'dlang' runPipeline() dub-1.19.0/LICENSE000066400000000000000000000021511360435400500133600ustar00rootroot00000000000000MIT License Copyright (c) 2012-2016 RejectedSoftware e.K. Copyright (c) 2016-2018 D Language Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. dub-1.19.0/README.md000066400000000000000000000123171360435400500136370ustar00rootroot00000000000000# dub package manager Package and build manager for [D](http://dlang.org/) applications and libraries. There is a central [package registry](https://github.com/dlang/dub-registry/) located at . [![GitHub tag](https://img.shields.io/github/tag/dlang/dub.svg?maxAge=86400)](#) [![Travis](https://travis-ci.org/dlang/dub.svg?branch=master)](https://travis-ci.org/dlang/dub) [![Coverage Status](https://coveralls.io/repos/dlang/dub/badge.svg)](https://coveralls.io/r/dlang/dub) [![Buildkite](https://badge.buildkite.com/c54d71c42284a042b9d578e28e093dff35f20cc8528319b1b6.svg?branch=master)](https://buildkite.com/dlang/dub) ## Introduction DUB emerged as a more general replacement for [vibe.d's](http://vibed.org/) package manager. It does not imply a dependency to vibe.d for packages and was extended to not only directly build projects, but also to generate project files (currently [VisualD](https://github.com/rainers/visuald)). [Mono-D](http://mono-d.alexanderbothe.com/) also supports the use of dub.json (dub's package description) as the project file. The project's philosophy is to keep things as simple as possible. All that is needed to make a project a dub package is to write a short [dub.json](http://code.dlang.org/publish) file and put the source code into a `source` subfolder. It *can* then be registered on the public [package registry](http://code.dlang.org) to be made available for everyone. Any dependencies specified in `dub.json` are automatically downloaded and made available to the project during the build process. ## Key features - Simple package and build description not getting in your way - Integrated with Git, avoiding maintenance tasks such as incrementing version numbers or uploading new project releases - Generates VisualD project/solution files, integrated into MonoD - Support for DMD, GDC and LDC (common DMD flags are translated automatically) - Supports development workflows by optionally using local directories as a package source ## Future direction To make things as flexible as they need to be for certain projects, it is planned to gradually add more options to the [package file format](http://code.dlang.org/package-format) and eventually to add the possibility to specify an external build tool along with the path of it's output files. The idea is that DUB provides a convenient build management that suffices for 99% of projects, but is also usable as a bare package manager that doesn't get in your way if needed. ## Installation DUB comes [precompiled](http://code.dlang.org/download) for Windows, OS X and Linux. It needs to have libcurl with SSL support installed (except on Windows). The `dub` executable then just needs to be accessible from `PATH` and can be invoked from the root folder of any DUB enabled project to build and run it. If you want to build for yourself, just install [DMD](http://dlang.org/download.html) and libcurl development headers and run `./build.sh`. On Windows you can simply run `build.cmd` without installing anything besides DMD. ### Arch Linux Михаил Страшун (Dicebot) maintains a dub package of the latest release in `Community`, for [x86_64](https://www.archlinux.org/packages/community/x86_64/dub/) and [i686](https://www.archlinux.org/packages/community/i686/dub/). Moritz Maxeiner has created a PKGBUILD file for GIT master: ### Debian/Ubuntu Linux Jordi Sayol maintains a DEB package as part of his [D APT repository](http://d-apt.sourceforge.net). Run `sudo apt-get install dub` to install. ### OS X Chris Molozian has added DUB to [Homebrew](http://mxcl.github.io/homebrew/). Use `brew install dub` to install the stable version, optionally adding `--HEAD`/`--devel` to install the latest git master or development release respectively. There is also a [MacPorts](https://www.macports.org/) package available. Type `sudo port install dub` to install the latest stable version. ### Windows Daniel Jost maintains a dub package on [chocolatey](https://chocolatey.org/packages/dub). Use `cinst dub` or `cinst dub -version #.#.#` to install stable or a custom version respectively. ## Alpine Linux Mathias (@Geod24) Lang maintains the Alpine Linux packages. It is currently part of 'edge' and can be installed through `apk --no-cache add -X http://dl-cdn.alpinelinux.org/alpine/edge/testing dub`. ## Using DUB as a library The [DUB package of DUB](http://code.dlang.org/packages/dub) can be used as a library to load or manipulate packages, or to resemble any functionality of the command line tool. The former task can be achieved by using the [Package class](https://github.com/dlang/dub/blob/master/source/dub/package_.d#L40). For examples on how to replicate the command line functionality, see [commandline.d](https://github.com/dlang/dub/blob/master/source/dub/commandline.d). ## Minimal D compiler required to build DUB In general it is always recommended to build DUB with the latest version of your D compiler. However, currently [2.076](https://dlang.org/changelog/2.076.0.html) is required to build DUB from source. # Contributing New contributers are always welcome, there's plenty to work on! For an easy start, take a look at issues marked [`bootcamp`](https://github.com/dlang/dub/labels/bootcamp) dub-1.19.0/appveyor.yml000066400000000000000000000077101360435400500147510ustar00rootroot00000000000000platform: x64 environment: matrix: #- DC: dmd # DVersion: nightly # arch: x64 #- DC: dmd # DVersion: nightly # arch: x86 - DC: dmd DVersion: beta arch: x64 - DC: dmd DVersion: beta arch: x86 - DC: dmd DVersion: stable arch: x64 - DC: dmd DVersion: 2.086.0 arch: x86 - DC: dmd DVersion: 2.086.0 arch: x64 - DC: dmd DVersion: stable arch: x86 - DC: ldc DVersion: stable arch: x64 - DC: ldc DVersion: 1.15.0 arch: x64 skip_tags: false branches: only: - master - stable install: - ps: function ResolveLatestDMD { $version = $env:DVersion; if($version -eq "stable") { $latest = (Invoke-WebRequest "http://downloads.dlang.org/releases/LATEST").toString(); $url = "http://downloads.dlang.org/releases/2.x/$($latest)/dmd.$($latest).windows.7z"; }elseif($version -eq "beta") { $latest = (Invoke-WebRequest "http://downloads.dlang.org/pre-releases/LATEST").toString(); $latestVersion = $latest.split("-")[0].split("~")[0]; $url = "http://downloads.dlang.org/pre-releases/2.x/$($latestVersion)/dmd.$($latest).windows.7z"; }elseif($version -eq "nightly") { $url = "http://nightlies.dlang.org/dmd-master-2017-05-20/dmd.master.windows.7z" }else { $url = "http://downloads.dlang.org/releases/2.x/$($version)/dmd.$($version).windows.7z"; } $env:PATH += ";C:\dmd2\windows\bin;"; return $url; } - ps: function ResolveLatestLDC { $version = $env:DVersion; $arch = $env:arch; if($version -eq "stable") { $latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST").toString().replace("`n","").replace("`r",""); $url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-windows-$($arch).7z"; }elseif($version -eq "beta") { $latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST_BETA").toString().replace("`n","").replace("`r",""); $url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-windows-$($arch).7z"; } else { $latest = $version; $url = "https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-windows-$($arch).7z"; } $env:PATH += ";C:\ldc2-$($latest)-windows-$($arch)\bin"; $env:DC = "ldc2"; return $url; } - ps: function SetUpDCompiler { $env:toolchain = "msvc"; if($env:DC -eq "dmd"){ echo "downloading ..."; $url = ResolveLatestDMD; echo $url; Invoke-WebRequest $url -OutFile "c:\dmd.7z"; echo "finished."; pushd c:\\; 7z x dmd.7z > $null; popd; } elseif($env:DC -eq "ldc"){ echo "downloading ..."; $url = ResolveLatestLDC; echo $url; Invoke-WebRequest $url -OutFile "c:\ldc.zip"; echo "finished."; pushd c:\\; 7z x ldc.zip > $null; popd; } } - ps: SetUpDCompiler build_script: - ps: if($env:arch -eq "x86"){ $env:compilersetupargs = "x86"; $env:Darch = "x86"; $env:DConf = "m32"; }elseif($env:arch -eq "x64"){ $env:compilersetupargs = "amd64"; $env:Darch = "x86_64"; $env:DConf = "m64"; } - ps: $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall"; - '"%compilersetup%" %compilersetupargs%' test_script: - echo %PLATFORM% - echo %Darch% - echo %DC% - echo %PATH% - '%DC% --version' - dub test --arch=%Darch% --compiler=%DC% dub-1.19.0/architecture.graphmlz000066400000000000000000000062071360435400500166110ustar00rootroot00000000000000Ks8\e*{vl'UI{v2-7"8mC)y&F!W%"h?4[M&YǴQכw`d~h'_OjB8;|z8T$RZAIz?E_?$ (8߅rCP(kg'~e6NpW aҷNr.TDiGc>XnZU]*Ueyr<ZP6 3ٻdrFE{e}X<}˂ x9۹1? a ?S6y6JéߠHSHF50h !;0ê9M\Q,jDdɺ([QtUɄ|E5,i~Zc4d\LU|#n ^dӪ,#9sn4fk"5iyi(zaGV..b ޓ((Ŧ*X%0/ypA46J~*U,y?HfepEFbGcޏa^%Ϩd]Ez0`TOyM 9A3ԏXw~N4u>x՞)_P]OƼaX<2('S-<WIBtb? #H|u_QWb`Ց٩?r&88+F[LKd|: R4-JPn9h@}J0ey2@YKRpDm_,Y-JDk1%0KL Vf6\A!\ Ys%j\iWK"KAXt0AaОLSHqVōH}h`-]R.]O WelziK;a4Dn5֖*Mb}y$57F#L!p&I}سAklh~s>_p%l?[egxDfXކo øi ?UD:EN)kiF##1@ymV +c]|ͧ< v[DУ&iYߥ%Q &#_(;8 c6? ͚cR%>r< $naKUSY$F' ;h=c.RBmRTjdf٤;Z^ |둬jrgc|1ΡϪghIĺnAn&* [ >/z|: %t/t45s˙ǰfo)ik:cJ,m xh;OEE@ٰ7ql7U'o^|_~PUol-R=̗:WQdGT|ɕG`ڲÅ1Qxa q!Oi~]*em'"ޔkOF!VoVݛIwRnw̺q0HBR$46wpSe=.EH҅=,׵{<}UqQR!_'_{ncO\$d u0jH#Z02:yM0lS0e;:ywGirKˈdb!ʘQʜ.i>)4eh2Ï2_5z^ 6Z7N^=#n =dՖ)1c!<ЛCnS/a]ބ*ccȵFi3ڌh,3j@lAptMbM D/3i?cl#&WMQˏ~0h8QI;佉j9l1q̐iQt>N|=NP5}w6Ǝ;\bc0m5:nW:q9!z "0˫e1I#Ql,d/MTsq#tĝw:qg;q&DHz&;!Q%+B/ER~'W|1)aNoGI *ӛՊIC^3˗!"B*d>,~ )ZsTh6"27\ZꛆyZrKۼLkU}wT%-چi*õR=-uTC6dM1ٴx-g}_qX 3]mlyWT<\WCcs!9a{^RR 5wBlISRJLho7 FRS\+ly6,zxdub-1.19.0/architecture.png000066400000000000000000002512231360435400500155510ustar00rootroot00000000000000PNG  IHDRmIDATx XT{Y/*J42JJLJ+PQPq  2m,0QQQQQ\we}_TVEHͬ^fܹw繏0❗=39>BGP xBGP xBGP x@_%SE`(;wdK wޥ*G /͋7nܼyΝ;P <``@SMyVTbW9]k2vUݤ*Ŀ@<*Jj>>;;7<5#=e݌pNJg#ތ"0#3Kr>wG?p#˨<0Erg$„OnkԯWOZ%9_ևc;#YtIyUWnzϡgb^ C{y*!Gؼy ryq᲍-Z<`ƚ]?d ܌!*wݻo...3NJ  nF(Ќ_z=[v7#^fcijr+N`7#d+J嘆8\]qR.j:S'$<4 WWWlAg3 AegN"pW6]*D,T$G`"(/q<=.u4JDж3# Bpp fGryDЌD0D3#46##@c<{5#،ЌpYh3Bi4##a ?q+#ӱât6#1fC ``bccY3B5##{zz޽{wGPj ߌoFH@$jjj^#w^#ȻHf8oF8ݻ&L/((݀G4,jӌPn"R6#ތjfxooo++SNV#M:QO3vft1rM!Is3<m۶YXX+0{ r3B7#TЌP.8ݻ޺}6n<`A>Y6#ěl3Ax03f̘:u*<`$mFS3<wvu׮]z96#!IfF`L(bx=f 6#5f4Gތp0 6JG#Th3By&Ҍ,%#ft5#Iڌрfj7#d_ PF%#MmFȗ!Ō@(ZZZV#$kFȖ!AfnFG0a<`7#\J`3#ᰀf u[lxA~ьFkFG >} ps jF{Y7#F3#4$ʪG(nlF{}WEhF,!4Ae3f}GGPaQfLIΘx3<HKEEuUUn<`FR%mF_3<HٳOG5oFy7#$Jڌp(#\zں0 f")7#dH@vx{{cxl̘1cɸ@󤢢:2$((oS-[ ɓ1G3UUU^^^`xxxL:#bA3RΝ;:u w$x<{73p7@S5&@Sܹs׮]322p7%lEOOϪ* w޵ݵknрG"kp/b rh#0?~8#Ь`'999 kiiSM#` (**rqq! nZ_Ν{ `ZKPNvuu}GP Ν;lI|Rc꒺v횞J* 4GpΝ;;;;_P.1aaa666fͪHTcԩ^^^207>#[[[7tfOuuI7oތJ-[VTT`//:^{}pezU|_WU||Ք)S^y17 ~6FGGwGWU|_=w/}|yb4//k׮M27TQ ƍnnno[YY-[  6;v`C%pDFF$fx6l(@ 4GjjjfΜIs•+W޾}[ƍ#P.͊QF?٥`/#B@f߾}۷裏hN1gϞ{nnnׁkPx|4GjjjvЕo„ #XZZ 2`~GvvvT?̯zl_&'ܹQ%7KiӦY[[oڴ鯿 }ǕroMM fr`@sbʕ4X`Yn7ll*%yo0ٳ1TWk[݃1ۗG`!Lsnnћ@Q8믿ZZZΛ7͛^8Gfپ[#`<dܹ1M%Q֬Y666aaa _|񅶖mAw͞FGGDPBH#o1#`GP8 4諯*//x++C^ZZПq%!z$m&&MT]]ݠqzoF@uS#< oܸa'={%nnnK.m3<'Nߟ;w.}&==Tz@V ,<59*@<(#:t##<`ϠҸAL6ݽK.'Olܸ TNj<$9CSɓ'߿_uV#ٶmիW^vM6<.h*[d'%%<e =Bxx8ȑ#?O?M6_~evvJu/^{Lz_~&Lf\dGy)cǎyzz~'ϟ]IMF߮@'E3fСC[wE4>=fҥJ/??@C߲EY[[,֭[qtx>HHNN~뭷 RTT$F쬣.dժU*•W[uЛ釜5kVn_/_NLٞK7lJD߳ggzBooo%LG^0JBGGGc/GU%n+lܸ&//oܸqT/QsJ8͊++(I^zyyy$&&Ҹ+8c4m?l7@8W^:u*Mm.džz)..o׮])-7D~'֭7n%dK*ꔙlBuDGrXfi.\8{쬬,*1 iٚR:k,1cZW X E۷KJJ-2@*RXXH#yМ{BB<}<ж ;ؓпޫW/>A9ch`Gs=7x`ڴiW!>hQ6#{֝Р'O}#p5zH`sQ۷ƍX" cƌ{iܣa<;FF{BIǏ ׻H FWnJn3o< .O4 V4>'}P'm0mj,nG`m?ޛooo,pf#MMw۹sgF4j,:""=ʕ+Dٕ%mYcu9@_KWSʖFРz^0GРߢ5nxx!%4J͇~#6;֥Kww&.d|}}5:xjjj[)0A[unzAyU*W7lؠ{U!Y|u K7li w*e {쳨ux-@PX |dee%3:u*,,>޽a_7jē /xNan޼ٸGGG}hMk܏ݠ vvv"u=´iӄxMbcctbC˴%˗/MzJuhb^>e G2  ѣGME9~͛7uԉ۾yngg7{l^πA[GLESNXe G@zqwwo3A㹏Ќ Yn]DDFc@Δ888dddgƎR}WqTTTPll۶ e z 7#ШLAK=ȁs5t1y= (@8QQQŸiZa۷o[YYw[ m1GȇM&L0Z׷GP &<h45553f̰32GPYgӧ GGGy4@]%W.\+w圯:w*V\Ut%w^iZqU\uWJw]N+JbWJ̫rxW|]:]ٗxWlEɼwEӕQIiJW\]'jJU\W9]j]x ޱGZxߢ.ޚ"/w;GKx"~x׋p -ąw^έ x-#5E>)("?!e0xTAy (4Y YPY b"G`nۺ' e' :u ,4$ >Y7Yu:& W^y&{߱IA6 LftVaըX_^K FJּp(_o5RFg~j0T5-**pKԉGtti 4jx djz᭧]ѣ6BU |d% JKK\r-M Z9x] ,?Y)uM:O LŜ,7Y8#_vby=0^i6#D7UWWW=ђ&sbj2isN6WDxӦJ6dǔvً/P3GGZZg-DyFA@ i7#dIҌ+Y3,$&&fffWUUݼySdME6#􋧄źj ޜGV޴i&MBxFHc]VVv8aڴiY YK1GLoFHRo3 ӧO'%%WVV :OxnF(ATR(5#oIkv2$]c7mXddd\vhA!!ru k!k!!M,4lI$mFG{jҋjq DMzQ=/<@B֒75G0x3BqiF7f< &!FE#^3;#oaQ@_נ#hd-d-q<"\"G75Go3B0@3B1f3eyyW#x-l jEx}P:Hbhšޏ#6#dJڌpFf=-#";=B$mFh@3B' M؏C{3BfTw^b'jo DMoQY Y̳"<#D>}8f|IR]3aDR-vJ)*L ),J5JΫ tE!6"A㹏|`YKcQF)kb]cAbZr,tzфSieL<X%Vef&7#>Sx"q2Y#!Q"-v2mfΎylJNOo0m{ܲ믾F^}'2du{CӧOBe#rYl hAnVurv]d17/L@A㹏|^7Q4L֔ZLˀs-jDzmyg_wwvZ>ݱOľS`Fg ;;;W1' k,HhFP|~\Z<0tCcēmU~,p"ޞG5Y˙{oLyܨuSW׌0ᳯuy.!y'\a<#/߽'MểBwv{󫺫цcS8R8@IaifG/:(1bͦowuHʭ4b':g6@]v999hтg#rߴY&G{i\ZqJ^e`w:\46l7 D%ieZeMO?W54kO >hz%,kJ.~U =nJڵ+}ɓS׸8Y4QSzc܋Zl1%qe6oi9,p[\D}L/}K.TwOz˙![l 9y4滟֌@Wz8;>W/^gxiF9 ؉jUA,5GYj9z|Nq5K _ׄ8#J7h_8^XmպEڪ7? M[syaĘ"xRos]兯ũ`ng8Aở?u=30l?UcI&LgAnBwby}ԄzNtvu"h}:}C*!==}Μ9666ѹs۷o\f+VZRۛ6Ȁ4 c=O5eO7 [1fbЖ?(Nr6!3`ĘIOgRl?֣>zaԙvܲW6dG?q.W|5#f-Xʚ3oQz!t}\~<<.k}?{ 7~u[g&>c}.JY;prv;ؙ\6^N)xzY?z4.nNo?EiJs#dko~\H+s~ GoO嘲_x}y`mhWbFz}~yjXb漞}?,`.kjQp6k!<< ūk\P]37ArI]]N']XcAY$k$ѱ8qKY]cAҏm~_}F>rl|v%ĺۈ?>T37}].\i&#x4W(xo]ChJnCG`e_D5Ealڹd&mBwfEKW.]Ҫu_Q^p0UwoleՆy;{뗮 @hI@Ȋ 'Ov/+xQz u갽(#~>, җjD%Kh?6o8J``Ȯ 6nǗ:/_J}rlŅ2Cv!=}ߖjG>oѪkVlϵ{b;cNb{t =.bloC L+ :.[$ T D(u 6k=§էZ4X_uc/gi|{hf9p!;'[(e-%WB/ζ=V#lcVJRfGX*R :F!OV >3L"h•W-ӜGxw XvYFo ioVm(;vъɳԩSU*ٳ Ek,NX])N-ZZ$ӹ Q3.N۟j$b?$ ndF.NkeQϮxֽ'o Se30d燣syūi̳hF>C1JIJy*gܺ ~t]lm1ڮ]oݺʋR$pd\ɢ}ǹ,8Yy ;v޳}nwH bcx];lٲefQ5{YRX&~j>MWye n"} HbQc?>rฬrO>.8?!.xR1]_ܰ@]CEJ T'/V/ANVz_ֳ@ycB;q>PjQ~ފ\3s{k'(Jɿ֛3߷ w elO?5bq V>НbxF6 N?r/n85[=MoApa l [B?jKy *@MZ4?xp?Թ{jjn9]:F9y, trNJ0%^ǵPeVg݋a;9uc+RĜ4._ |_|X-!l"񔲐OwNB~s7Max]Z`=jÇծkPWĤ/IN"u[(lelmGYzpyqC<=2@iXsV#ֽ3w\֚mq;VVnڶ20w/BBϦP}2嫧ӟ2ՓZSi^:щ4Zp(&3ύ7eu 0ntJ_ԥ/P[/~=iL-Ӿ.**uenF^D?Ukv=nd9"wd-~KKKdVVHuM'aʃyAқ +D#pAI `qyeRQO̽DՍ&uRxx<@7;*#(ʙm?$>`PQ^^x4Y[TvF{=(5 ḩӾMObi3jefdhLŏ+Hu=iֻ_tzeY79G1k=eyGН)\&WR<'Z-_jC36ϩ y4>TxP !;(| {#Px vܞ@4?CG#MM _eO0evϷ)ۭn% @,kE9FCebr;4E FVyw2cu90X6Q̭Vr=yoO= ]F]*jZ| mJII@; JԺ>V׸  F2NTd9 b~(  '^w(N<󋚎l{x}vg8zbC.6&k7mAM=U)*4T>j9d:~]Bn”zfoM7hyEAG̍\z0@' `ma^a# ePzߍVN:E/=sI4~#";i(/\yꩧWpQwt*}8x w&J:~8lʰP&7e=AlI6qa4K#A(2dxYuc&Lm##O,ذM(~.$g:ZBn DJB@rְ|Gw%rGKZ[]E]pd#4 hFPz-xz}i UBzcrN.>wL0 ӫ=zeػc[ھ`;({||Lߏ'_~{Ͼ>6Gq#z!GNT: ez|mҽ^x=znw~^'+VSjXUAͲaņ]-OW^BDAG_^rzzzZYYUTTۈ\&Ef̦}o)w ywoѫve]VmGZ}@/ uGŃg_\#գs>wv_ x"t/^xf];53Ntx5#4N#dƝ\e^}>ߞ*uvj޲36ϽoۍrV3M)w˦h{mP~l3Ĝ\zMufY * K#uUrj=ka#PrPk˴"m_@ҭG>#~FjCٶn=x}XG)f/ŷ?-ظKx-b(䖮>M=ny#|2wa)8;w]wA=tcZvS-c`VTN4>vDB~jec`c/L*䬶c`/L9w4@üc`?r^1+yTrAFa,N)Roxvtڅ*mx>Pp:fڵUy:t]W|`fI)fY+6(%B=kϣZ] f/ZYjŭ4|*ƬΥItd6g "0kQ17~] MuʼnQIQBVauw_lWbjZIȩ<QƏ3Ng5KDp–J+=Pgֵ3C`GhA+/ YEUqJM%g=Y`!v+2Y(9\^,ϏI+QmyIIu)#GSb&ߒ{y $1DgJd5q<)TIb~U#xfMoDKԖZ?y =&@B# B'Bz_d'Gv8Hqᬉ4# ,=z݄GZZyDYEL54Hf4#T~Є87#Tb'x-l j?<@B5k!B3Bz_d'G0x3B)ԌXdʋn !f!r8Q>ْ6#$Hڌp@ ɤ"<65 D%*>˃^<@B5k!B3BddьpNdU' wFDG0/N& Ax :(鹏&<@B:(G@I#p) MAAT& LAx {___x%yBg#4zФ8ٌoޏ#`/v<65 DYxt]CS< @B2G@OGC4#p4#4py6#``HN Ax xykNҽ?j @B# B"BpB6#1fҞ׀QQXd‹#hoaffGZ#@d-d-czDYEW|}}݌*i3B D:xQiJh~b'#hoaQ@`mHx#<@B֒pbLrM!I3Ay #`I/v|uu5fܹsƍJʕiii񒄷ѣE'XUƫhѢh'66[酅B*=´izr <8p=zh9kIˮ]~>U֒O]3('NxI>޾}իeee)xY5bgmm6! E8lYhM,u(֨ (Bh[ۚn߯^\.ι|ܮۘ?uWZzI.((hĉ| J ӧO?իuuuf#Haݻy^x\U^^~4p3f0wN> K_ptt/^_eeeuu5T?Ioܸqҥ Y. $?K3;wNR{Rlc2kr75&KQ+!!k׮v؎9lG-kмy:v옘h=QJ .Dҿ5 H?V,?>>Ap•+WjkkF͂5 G ='D[n\2A7K/9sٿv֭{fDٺUDx AܷJ Ç!Aum|8vojjjݡJ`xw\Һs[NͲi1%%EAj5h1QD-( ?~&/Fe%:r|0a8Qٳg^^yGo?ǽ{f(nݺuUU#fݻ4 PFp7+gDDٳg۵kW>cƌwy\~\!566`㣕* ѣGII $?ǎ~ { ,q&UPPfΜ9Xe8Z#@v-''e <4%%f} |i ? =#q8 #`ʔ۩S';͛7YNګW/DB$ql{YYYstO>dŊ/x69Gм&ըe}ddd!]k,ZVǏs[>>7ZڲJst$D"gZC(9! ݻ5*Z#uRP⦚@)ꉲ;j8H9-*d@.8$?ݿM%8#sssyZ֩,gg稨( 6.( E"Qqq1H&;2޾QxAXmGkQdh٬a|/~~~AAAZmAyyy VsV#зjy9=UWWHZצ-c(//G7ڲrssbqrr2"#@Px{{ 5(YGPc]HPQ||'??? nz77H|]\\T*VAAA111L7#XRtvvy_dW("r9.LeԸj+<<<::9+Ax"{544@z.((`_uttdfTT_^1S%LD@]} Pr7!d^Juu5fD`T7fLJH$UUUqY¿P( Rzi+r84&|A0Jvxqqq0#Yxl9}rÕm$r8D`n0wBaI)͂٢BSRRtGb3+EFFD<ͪ%""|DmC`lgarQPVMM#g[ Je``EJC{{B|Jxɯ_9ќ{DƐlAA6244=ljhhg&` 993 b,PRpp0;-V:99K{UcZZ/*r(;p9d@ͣHC3obDBr<7"G`$)[PL͊sD&{Pꎎ\R|O^aIt*'?-r9&MHTTPa칹LP%<892|G'r(~d2T,T*K}JC%Q˲g+9;9&MQd*Jq P S'/⽏H"dffbP#辯?MKDҀNd2HONbJgxN uK*#} (Fr$A6{G`Arx+mmɋLQ9#04ƒŁ .dwO5VuIRA7n=ǨQ% Y̛4Q ƣ$A[X`%; OOOwwwNj`\7E&˨sА# G@RyyyYYY@TTe/D.0*%pO+0.O3;GPjʉe@2Gdw\.j[+!Ë&(& >reu#x)h-usAUU, ԡ(!hrWi8Gk@bJ~~~yD 𢡓nS OP&>,Dbr8Xɖ]`ggg ;f!JfEDD]mШ63#h@x>X999A_amd I"0T>xbm|{{{cQhr]m5px_An@Vr2TR Tnn+W<== Wmi4Q HPPA[.ՋD+&(PQkR|DdA r`c[-{eZް6UUU9;;[y1"##9}K*r9"A75)Vud2777)k0Ǡ)GDX8뙡*--x@ j{TT:^JZZ0*<<"A71i}#>4d'*((*(,, )44=4'ASP)222((_TuֵBg"$ u[| H`#`DVaa+;\ǎ%f4JmM_777l}rQ!roTSS h񯤶 ?(, Z ۄ흛/9Ug!V 95r=!U"޵2X,}4AFA5Qhh\g7ܨѨEY(9zk^&?([a5/8{VUWW{6 Ò]$ޮL*ʐs#faP#hރ% 䝟ocpR*((cMH~D"|ņp>jMLd8Ì%" &#XǠ@'$$D.[mqpp UWWb0?AR]]/Z/G_W555PºYɍ%,dPLI&A:9SjllXA 9X,[k^њZurr’K?O~AAAJߵ^w_7m\'cnbbbm#ǧ}40u J p<Ŷ`l[ۉSEkSߥ/$EEE% ٴ*`GлM߀I۱dgJ*]*꘩F CPl ՝GK8nOǠGP Z+ح5CJKKsttԽ_Q9` G_Eωj5h7mDyyy eX3^;;;[N(f QxZWP9v%(D=Xl{ţ%*JȯG$h8G)N/88R^^~XB0XXX)lk<} dG GPŒru~mZPbI...ےjr򋈈dy9-00. ~HHX,d(GJPg5GG^fkyPAͪ<ɂ#,,v*r?AG Olm G Dž D"Q(ZQjj*r 1p JPV-|ΜfO*"J`V|LN~&/CUUU q? \.00ť? A H$nA3mk*%8׀bCVQC|A()1xzX9ϴl#h4&rK.;99~#XJJL&v7 G0\Pٙ6;AQ(Fa9}nnn-2JUUU6Xv=Mq>9fD U"T*4#XV555mЂ}wråT*R)%(5iZɻⷸ89"g+feefEG$#جrss!EGG 0r`L(&50dQ#tTb“/W6U]]v$(I$Fkll Y? Gл9UWWYZZr+,zK|&jwh̙ĠGP̪P,Ko(mywU(22ۛ koCx19ʺX,4`(yQC`ggߓWyy9ga\ef3 #ཏWDDDttf: lP &6YYY Ï9<<ꮼy◧H$ J9#R9[B/q^ 'ʛc9[Uz$_jXAᧁ0VZqD 566=<<<Q]lEB!(Db68BlllK`9&111xM{`a宮ZM?"k׮;urM_#G@jkk;kgg'8@$J#""H~qִ8{lY4ł+$$/k`wpphժnc swwjr{{x{#G#>Oj#(rQIBm %h~2L"s`$ -Ŗ#QO?z*H4v؅ >|޽{F=,Fw-8N}֯_…KLUGh'xYC.]uV0? ;wb4C|;s̱c"GP+t?9>"D@mQ& l;T_fee ҄lK$;#\. 8H罏 +㏿ :FEt:i)͞=eϜ9## G`#{QP,}7777VV]] 񸺺 ҇`B{{{>~o\W1t({^7&M2[s { Oy\#?>~੮}\yLMϥ'O E<~*s GuSqzS9yP~sˏKMꩺ_OiTԓӧ]$O'sOc) Q9{S{s3MϯMϭV۬ mt3]AC!-#Z|dIr"(nCGн?M1=j+E/\,Lvvv;i~>_*d2GyŁ LSt4j=Z @K=%=FPRB@5<zaSoIDATVA~wJ1&'9aB;w|/8Bqqr#LH46=-m'ϲ1xZ&p%C![wRSS5Mppmrd???k.# G@Z#ﮰÃF#h=B  6/_|~5"TJh :`E`mc'Y!t:D-1LMIIH$[+00ٻ#0! oΎ Fdg8u/FBAoo˗ܹ"O*!GPےE*o[YD"]":A<& |n#FjI>>> BߣH$#<|[`⊊7n@eF{AmH/G0%0>XfQ>xDDt:Pך5kl*GWUU1{8r(+Ϗؖ8 -m?~ٳׯ_#G 9j fftUDDt:H888VD\.HBYYYN#""yeG0z1 VY(|. |VD"]":Aؖ8£sm>WT|)#<-Ӵqj?Z#`BA &{^(,DADt:G:5xp>>Xg m'-%C!s49=??_ ɩ9ro#o#h] pH<<<#0L惆 mCۄă!t:D3ѓV/RD"J)N#G@=jaڔ9s8YPx  $6?8}KGh)onr>xJU |Pch.z|Azp2] qRkEZbvr­V4`COU+_O_Ǫb8G vvdВ GRy6rD7'''[sI=#pR:  Di%tM9'аo 켣u^^yR|~ێ\`='LGNu|}¶l|PeEt8%jars Z#egQi)cP7z5=nC tC;2vTx!sr,<~\I8šɟL z+r{EjrD{~2=8i%__CxCF2r1eS!o_ɨYy%M5[Cz䐅˽C6<:`#g/H9EᣚAM͍p<&4r9F#bcLZGb%z9BK<L>gІo-)o_w; Eo(d`\C?=pbm?}=oQGxMuql"y'F`Ӷ;:xA^&nܲTO1@?ޘ*߼s֜]DІwͦ~O]q7uWdh/Z.v!u~}ktb;>C%XXֱ"moZ6mek%d"!1&؀ dt"cND&N+Y)S:c}`e[ѱ e `B3 ;buB– _] ڝ8D2j!oNUx76XA31!|0Qu?BI0qP-~#Y+[ fǐ-;?`$)P{|$S9G"Ycy^E,nST#K6ܐJ5=0pI$@-$M}I6ܸǑmx#Q@@YJ5ussHd2ۇ,%]@/F8e Rmf~S5wA{6pw A7E!u׹=|&}hC}nSןN) :`ݙwȸ^xQ;r?ogWv}{?Vil5ڐB wO=dۙ[s)6qBqt>XxvjxDz$ݜ^u/_R>ݯ%5dh/X;l̪ qϷT3]i aV#{S~~Cܓ_V)iZ?w7& GE~&|Hf&ޘBRz wȟ8h5z@(ւ%9YqpUxD{$m ٲ#@}&Nݞs z o.<| c"pe k)Kc׍Nqs:qŚ^=wdkS8SyK6x>n]R/Is^fv /H^7q+v睄WSRyѱFcH<Zy~޾.n^~+nڡXu#87I X' h%CKW+OGX)s΃g%A8BM$8$<)=$tZBM~~~؄9akj${h/M 앒.Fb' _\))0&Hl#i GS ,Z`%}hS[F6mP6|ثڸC;zٚ'0$lkۜ!z OcEKE$|pڌ9N}޶Ez캭|[shCmap@?oam:,[wA9vE _c'Ҧנa0%c&s}E:UhCd)A^)O?o*tc*[E Ok"iۮ<)siGaYO?M6WC_ T?# >NwȔϛlPom9mL,_  8At #&'g7MAC#,[)_w3d#9Wl\.j/ۿ⋳kCn2ؠ̀ۇ*Ǝp#$o~ cMM=f͙?*`8djÊu[lb> `bSJI=Z&/F8b ָAxZXXA+G0v=#|ȠëSluR=\ޖ'q]qcWW7q}UKu'oS%_nm>ׇ/:i'8ªMt>@ކ.)>5 E;,]Hb;rwCt{Պ P+u"FtʮjW3KqS+0o89'G+uu{8j.i盭~3`pHr /ՁC;Km#q!f}rީ ۵lu" ŗlc8_ ?~S G(<GZv&L=z&lu3{d>Gy oj0jB8!i?b8D3۷u| )]#)v+&= 4 ʌ+7O|fpnojCbHȗsvwĐ/T|oبqoQs '+j'Tms_3Y\޾uB/`_ *^iӖpT$y␴Hrub$CF!Tok#]>fT3G]"OC0IbJcWL%{UC޵{oOzz[O_ 6Glޞ۱S>f'@תH9rL5~6O=OR^QG0X8uCKWq |sV@_|8--{!jCu2w_/L E_,t9\$fuc(6eu1oĔ_{l}HMLbēKVj!_}wh׾;nYOR‡0'zmu׻<޾w~G8G`YVpH~$hA"$.yq$IA$a!H陝-j555AUUUQ)SSN%rIUꏕ\X<<=7zzJ{柾n ,ୖ&X!:$,":d t<\r]{7t/;t SZk!pAP,)}8r(fT[[ꁨS~~ A}1|+@hG0,/qsG-]?ű A,3ja".bC2~|%+D0 CvHΡq ?,]VDp CD"Mpz8r(f,`ή"KI> r;P#A#> Cʲ|'|DDbީlvt:L>2G{G!%e~GGl\\<*7X(hբ 9PWWgkAǾ$od>H*eVކGx(>xjZ=|.#|p/mc35MHdK4!z ~;j) \|Ku:!9y<), C'Du:Gܠ0 !ZcȹwCJT7_g<h:[CLs+e75cȡS_ᐦ0•CCH؛CGl\r?5y{{+J9ۥ$Kk6/%M]`\ HJ6~='RZ?1[b^>H+uG'~ >K[RIƴx| ͻ͟HdKd ^YWOfҋNuX|p|q:&GPO9O62|>Hl[vG^զ9^6A>v鵎իdZ"t`A8Bvu[`PO{M:hȈ1 \)?wO?w<}h5XCnMU|׫F}3l9 A3}%s-^|c ci2ۿZcM$xp%2H|i3C]:=ts,s |+7Ĭt#\)[A+Aްyҁ%>?xi|j^S|33siBݑ럅~*ED;ۅˉCV)qA>lwYM<}z 9]q}_ 6j%AMz&NObUb7JcY-s W[w#4D8%$xXOgA  1F|=?YtxY_| &79cXrūZ9"C9dܤm9'7"?ݸ-1D !{UJ?m ,,s/ϰ1;9!j&yA!g⒛#W0D]]]q1Vwm #\5|1#8>BIg [LX`G}S 䃪ڴmG6ǵG&*w~/x'OL8xƔxEsgђrΨ"xȖUjCTίGǬA|ꍩ79g~׻Qzў޾P'f~ G؝_|ݣ_>t݊w̞nԸ~^Ϟ p)0}C⒕m;$q b՛Wn}LBb2}h3'Ys^kp˜q4w'~#.%a-x]H]E$kdd֟B 7r_͋EB?7r̄uIsI4 c0x52#eW 1w}W%RlU$qBژuV+2rf;l칋Ղ?!=Iʔy ܕ:R  nS<)sҸ s mY_~z{ aM#40ƨw|=14z8dh0ɷ {uTb/;uR{ ,Oڱtce>R&d"Vv\]L6jʍ0Ͽp \!OQjjA%J{Ae`|b!¬!t Z`~)ibE=Ybf-F -% ;rf9Q|_ܖC ZhFL]pJKܚ=p-;w>Ԟ^&d\/[py]27mo`2,@Ƶ,.wȸ.p5xv%c/ ǟ{%W|%+=nq?w;Tu~Q76¸Vfqw)>]~I _G..u\vqϷ^ROg9C[D"])‹/nݞyQpB=Pa,.oV (,^xz=wߞvv%u$7#\!$H46iǶ|GԐ?hhgk]9PE5ޘ4sda8!/@'^|uqȊ5Z^_tFn)?eww=b>^ G ƸXGb11I偏OC]^-֭NT8cgo̍"Kq({O\Db+O8C"π1)v5{@`6r0¾C>@PWUU C  p6T*s!Hg^4y1<)Ig]C'T ,FX-F6G & >9f4#Oi/5Nm_oj:ҕr2g.q^#5wr+p鿐q} |2'O+(Ci!s::{ ;m; i0W6+Ae /NNAÜ^sgXd.qͽ N"[l;89oz^qh5hڒ1#YԐ=cBc͜HdKd F-S498BuGؒp=MN<:::ppK_)=N -"EG 184?`oaGoE-h!j! nNqUs`i48rȌ9 sR HKK@:oD&!G^6{j?P\`bo9vb? \@OFJV3vPؐh8}Ϥχç.O6kА,Ǖ P}F  P19f4#\q6>uѦЮA:9w)8uAm\oܜM܃ףJГ&Q66nrhӎ] |)(w>(߼~OO::8]^F8šM;8uT۬}DT Tn!6g9\Pvίw#a4h)>8D0v”)u/ݐ|F14s"q1G]K;w%l$l.IE~p#@q $UYmڴS[.tu[){PY2zǓ8EӯSAU(Regs:NEaF}*!ërR~p!5@℠.FZP1~FO!;6;>1Gx~SO!۲ڴm!cw>E6ŐEL#@.'Ơ(T%$d{ a$'vvoB0ٺpk:k]G8FCDޠb߈H,_ͩcB1#DFF EP ## Jd2T*A"""BBB8-Fv1$5[V~FU¸6/J{$ǿpyJ^tuէP=@R:u~w7ߡ82_KVà0>5Ͻ'(RsEހ?W2qL׉wu^>/ٷfa 5?ٽ@t۶ MS͜HK4!z rbJG_/' &NB9$>?##}wpElKgGݔY!:F!a,C[)냆|_WEO8dͦv>?K'_ {xO9g #sDQ fn1:C6$5g\46:Ǐ\ьo 8ZR9quQw pȚM3w , F6ҝ:99=+ hr9#<^T*" /Fq49)%F%rHr}r>T0yC=ZoNqp_~-Ku*5`Y]r܉ڒSnZ\Iz{?=Ni9'+nAC1K4cHŕ{Ԯ(z )t^)>S!:Yy; />}Xuws7_zo.+\<aFqt$ŵPl G GlJVbChggFDVj᎕.F8wE#<{ dgGXљ*G8š􎝺Kwqš#GHKKI9BJJ!5]g>;w[nv'@ NN=WCs9o޾➇N] H8eO5%9cׁMs\ˉC;gEWu-F8sK10جCtF=FsbccI1#@\ MJii)r(kTPPPTT~Ņ(iO=2[JY(P  3P8]y}P%s'#U܆__ A /F0]9BCC#=X!|ྎek?{-N5_0Zn+c!B9|>,% !-_˼CN5C!JMM5#T*&bD҅#RaaX,F)77ÃE`݋*/5g~Kٛ+l# ukeHjM`5d\2a".ACrd#VY8??_,s0#G0#hރAx"~ήU`R(Xtբpdooos>jM86>Xk(,ē2C!'%C!t3 ZQLLLhh(r(\ .77 {1 ֽjF8B}}O: r Cʲ|'%N$%C!t#r>fa???<"G@ү4\`BBBD%W-G+ asLr#}`]&kHlj!t:|DOFrooo6.,g[qxbDŻDt:b 1g_Cdddtt4o}}]CCr\aXUU)---b,xjѦ8mm`p=(>HV/c"ѰXO$%C!tZ>o3#D5_7;;"[# G@blPV&/FBzV-Gx$ĭ z95;Dg jNlTpI:#|>z=C6h.A؈C̹1>>>44_`oFCGq_rZ$GaJT*e#0/W-G>9M8',O|".ACPnյ9/9= "[d*,,tqqa#\q¢ |\hkAx[Hyp#>xƢǬo".AظC{W*2 3r(MIRl4\\\,FZ U6Am_VFb^$Xiщ O$fa"EM ]":A~[Vy-xK%r8H$B Apuuŏq1NXYP9_hꕪ*qsA3oH,D"]":;tޡܹgL1r3L49%%%&)%H$SNQDQaQ"hRaab""""(wk>;z_8׼yǴm)..G@>$UUYe m d-z'G %'''&&#c817A&Jزe˦M6Bn{5b!bh}mcccLX8E3VmjjPORm`io2B+9ZfRTĭ,G09}As={ڵa];|J]r566RAst]t8>2@9#Gb L9K8FA%pE(333>>VUTTHU~"Gp8d&9jݑTǁIRBɛ9)_YYY5Gd3g6ô8SO<Kmmm?r}ҝ!)!qqqyC#444 m0KѨd:j<&#QH2Bk(>4 ):%\$A 1N: _iii?tR_ GtOκ1KǿC x+ ,9Dʾ,udjp 8Я"Gh)M(6@- TRw4iҤEsTAܯh6~d[J|eIʇ (`W=\ߒ:ӆϮ}/+ ``05,/ѨhRRR222\߱P<9~8mhI{۷A;#  hڵÇ8xF|V]|9BBĉyq+4MMM 89 JKKSh%3(???>> }Ν;g4iyС }2E`GGGWWӧ':;;W%\mpaÆ=3P|A̡ΝKoR+;~a\[gΜ7n߾~EC (K.E8B]]^礸8vGGpNLTPI6-A 'SN8q eA[I$eUI\%Y֭[{1^}Z 6L>s>(Fí<|p:xcVVVb4u=k&j ]!dgg4#`_F9=WVKjBOE&? :¤e\ٳ[o{Ck֬>|8}ںuk@@;@6>644AW W$IA8 2yfTDKLLTPJ9Xݪ@Fq̘1w}wgg'FAq={v@@+0mmm>,MGPGM8RD4e>jW)lpq* GJPy 6`(gy[n1iy-D  gj6 G@>RTYYhx^~a Np%xK /Vpp#ܡaÆ7y4&6ѣBXXqXII R ᪗kѢE!#* vr=Qc\jo&Ie˖r-0Ȩ~!%o/~_QQa@@@hRJUv&??^ۋ]MMMAAAM4IUL>&4W�}Ǐ?y򤢇1w &!,Xj+ LuYWjjjRRRj4+::z{{t ?{JIGABQX)={;wTpqr#͛Gυ:woMlnnhx,jzT~~>?h4MMMXJ#@VEEEPPh1no!6P6eme?̚5k׮uӍ>gXW^!'[Ԗ-[z}RRROOӟw ڭ&I;ή2>kb)B844\ - ?D_Ϋ$8z״> )Yya}@PSSSpp0M&Q7HWvW3+;=6T+ZV~϶هTA+Kmsrr mmmd`́#HЯg%(( CвBstsJ#J u7***<< ᄸ=effJ dF8Rvv6kfpp+'''22 N8@~+11>~ީ`(<0,~EGGp***R'G8!DբE~n'4ph@QQeff&''cMz + !si$'y:A|n ϭBCCqBsH bp5q@@@vv6~Zh?l9ҦӱGBҊL;F^@fHKKC iEEE@@"| GAG]ZPOBO*[(}!w(33_ܧF[xȐVJpp55?*rsscbb0뒷P#dee#@RL#x222Y'DPކRv4* hP1q$+ K85@n5^ڃ^###Q&BBBdQDEp8#ȫVFCCP#'JKK=¹[ʈ`G$ (###11QK;J,#_8(W!!!h!IHHH##@XdB_Ձ#[=O쇧°GG***z=XJ241zx gDBxUEot555p;1^Cqq1RhGK؂*]2T&VVTQQATȲ2oK{{{cbbP9(T[~TqOF$GKVt+ 2$$Dko^QQ?uСtO=6kAཀ?cJ-Oi O8*5i$%#@Vwwwtt4BSRRe? rrrdKٞ/N,V\\\zz:Rhmpܡޠ ($$DA}n pMxp I|???W1G0?f*8KIIIrV8 I`i#%Iiii(99ٌTVV_ZZ1eUZ655U%:;;CBBPWIܳ(L4 K)pX6InF:䐻qܷwkVs FD}Uijz}CC\`Rʋ8¿-Gl€J+$#OC8@~,kG<`v*77WyI3Ksuwwʕr! ) 4VBsܚ \JMMLMp'DmTPP)˯Ԥqco#_qPZ-V8徬}AjʕYf _v dO˓%"'%%)7!88IW9NGZ[[5Mww7B}yu nJl}JrvE˳+o ݴi>HwR J=\(+%"""t# cDI*---;;#x@,+A>yr:_utt|ĈǏWݫ?a֬Yo-!Oj@ 㡆Ԥ$.$h蔛Lu8BV|q<V. GDAGh3td9b} w?;nvcǎ$?={W_пhȐ!?}n6x?O}ݓ'OF ,222HLLD,n-Z(44ꖟ\}w pTwwwXXXdd )"===HH_ iwQy'ŽyNgŽZV1ݻwO09oRRRdɄȫdRTTꚁ#((*k kС*k #/`iua#deeY G1g {ܴ[Ǐpwk̙SZl =]]]t KIIP\ " ;Wnnnxx8E͌pth4`If1GPhfi 39`477[nuww3fĈy}ۣM#N|oooq-466r>}:!RPW&5VNNNch?I_#A;+eJJק`| d3@ ZF$&&b|h4-r#X& \H.7o6>׬Y 馛fϞmǎn:ݻǐQF9쀼DJ=k딆#df#I&;̨(ZU\\O{֒׬<Ǯ E!Q Ϝ,w}wuuFٵk}for&L0@N7qDŝ$E؝RpѢE*(FjGQ[__O|u+**ݥf_'v2dCZC=bdL+++}YX#` yLWu ɟ_}'hHb a'7 F,477x8.Z6ުi`_PP8I줵,[;d q Ps@y#>`<>hȐ!̠ϟ?/SֶmxxWO> AH;3&L0YnmmUj +(i8~ @ "P2uW kl㣦BCCm1h ěhrJr8ۣ͛xxK42KNNp@9J0wfޝƪGI&eggc$G0yb#%8*!>B?##c%JMMΰ& M+ `RII }0i`(V``m<^Z A: {K<Ԝ6?&jD 6Hd86iB<kѣ8%*++6@rRIS F}WJJ ,dŬ,eJrŽqff&5ᤳy1#]+::~d#:;;5Mss'Mww7ͦ& rxx8hqHЌ3XQɶ ( d;Z8j9v;%vT2Dv;jd";xNN:Ö\ۦDקү0?4GFWp|OmZaa!mfΜ9~xq&MR>9777..@ee,9sz.gg\o߾vьF7~+(Nc) Do?#: krfc@QC8qٳNrEQ(AAgptntV;:4d:pÇiK3;C{ 97bC'|"lZ`0x#z/IHH # 볖psYsY2$#ر& <쉎GG Nۉ\$#7sQ{ysy#{ϟ?~h,Cm2?tV;j׮]:s[Oinٲ%$$dG6>~ p#܈ vO'b@A믿g8BdddIIZ+++ E]9OdK?3-e;vطoMggϞu>k& :J`5QdjO%#0Gܹ~0G(8Jemvfmjkk;;;O>M3giӦ+V56>p#+8D >NOXj$Sd1sړ`RALFh5NQl.鬥ȑ#gΜ# Ar2F6nX__o0? kwNfDm6o~Iws;::o= 7ޠ. &aĉdu7bC| mqmmm:N=QdQb e d]&#ȓi2[>Q͇#ءA-r rK dn߾}ǎ#RJ訍7644cA(u֗_~Y}3g$K@:thGGI?pn| 'AoV@"44XśdY#n,Y=9ܝ~zn9JrЦC9BVV@e{1ZՍ7nŊ W_}EoRՒpCA ">z#$'''%%{"r4SR2MĨG@ X#+4S{{{VV;o6667̛7Ϝ#p#+8>Oѣ:V&#M6hnrS&E%6Y]МO*8hb&FsUD N6k&paȐ!.>FWp9|l5.@ jWJ,BSSw((=GTPO|<ڜ;&F61괳n_%`^VvPXXh#|yA+::(p#܈ A\Oldҥ vGL r4SE2MĈoIG@#;G@ Xu+\MN ke#&N8ȊÍp#+8>O,2J" vGL111 #9re\r41l#IXt#,GmsALXE!z3FFO}gg UUUT_AV?|2$#lt.#MJF#O]~aܹ| aag_7bCD5k\wus"""u233i_= ?q)9Я~|4t9MHy(SWrW^y6GF'}>;vq鴈r+G@U-ZD L 1GXP|eLA#'#PVBnsGFWp|}rW0pp>%%%]]]}F#mĿL 3G@s>NnG@#71bv#O]_rq,F6'<̼y}} Cppp\\V+44|7$ep41RR RG@ X.N] FF`rA,n1_!2qDU>Ѵi$UUUZ655 ktuuvwwH|Jo#G@#w61L2O%`e=u%C9ɹ!, p#܈ O|s kH׀|$#l&'&FJJF(~8J*,sqB K >{87bC9TZmMMcbb233x^לU=sMH(.8J*ԕKn1_! |OxTTT"GXTTTpp`ڍh##t:8 zxq41r)UoMё|tt#p#+8>O~p#3444&&6޼1...:t(^ݜ w}|s41:bt#BO]9Gp}n|'#>#Я^XUDqqqq/lηMĻ>8yXt#KG,:گn1_! | jJJJZm^^v8.h4r.9x1G@#{HF#{O]A¾p#܈ O|"+=h4&$$bKLE9ɃAp@A9r41@2F%#pT[v Kl} t#p#'=}555iii8 (** ypY9:Qs>\+G&F-jhb'G@ XZ9BVV#p#+8>Ob= G =v‚1:t>1؜O&F'#ț3GTi OnÍp#+8c>QOx$68TDDD\\m 69qp#Gp>2pCs.5e\rkbT&FbGqN]5"@% 7>q# x266SAA6 ]h~ n׀|\r41rU\ Xf'9BaapFCs ===IONNFIEajFCGP\2–{h.nlzd.۲sˮCN%#Xm杝<7eroKFذQuwu*QqVr~Gm}Tt9NvRC5}d2? G΍[w7 +66RU6_YtHՎG!g9|bm&XѼ'MKK H Y<:p@jjF JIIILL8#t:8<^xG5}6iCm쪫}YB/ JLاb(e˾cW V{Ï,vC?/9_ܜ7m_}ՃucYzw "͚EGTqMx}qۚ:|/˘^E{6aziRz&km/SW󗔑 9s^KvU#1{s~#c 5*nu㋯>b]F?'N@RYLx5r#]#F=>p 7gR FɢE2338_pHߒikÏ!w[B%]6dkf9_geF>+3 Ų˼'^  ֭7nOdd vUUUxhwoX />/ ~tooĪ/K6is\D#|:";ߺwc>_6[1G৉/({sfgGYOx&FVіo-r#SkExWf*'===UZZjFn>m}dkwoX^q#=#hfL}!#lk5?1y3GE{`?Ox~ƝL~ht8'3c~ޞ-MJI1Qce841i8A3?XaC/Nzsd#c=*s O$Smk>Ҥ|h++Dا_ݟI2E}aYYe?(G#}Bq s W{᪉ASW9B p]Qo?婿&lA?Gp٣OĎE d[ZΞCO]ǖo7/?B[#G?Nכid?OHjF4>#Lpo|CDo=F111>>>lO@W6Nĕ\Jx#WtadtO5[wy>_櫙VSaaEMk3/>8**>̚=9k?[GD>:*j,?>KV>_3T ;!߭aˤ{zLdF?6Z)1租]ϏyI2ܢo ZPfeWU.OqKڸyWvO9/mn0k֬niE}/Goj4[ou]]]>Bbgdd` [=<\voXrkwuUld}#DF#,Ō{O'4 p=?6/_t u#,,^b[Ky :.5ًǐd<>rFW9s$ u̅t \3%l.s.x,{yVv}A}Nޢ?s?|ny\f'7ٟI^k_ưWg[IN>eZ7o(ϋjb$vOAMٰ¯WM9sj]-Xz#dL˝"ہv8¦wss/ 6r,:s_^r ;y+j8B%G--j)>bdWnoEqqfyO]L>ف q:+1o=8a)<񼢯'xMl~`i^WLsꆃw{IQsFVg 9 ٿKCHh\5.n}O,XV8BEԳ"&GxhÆtyK^z¹~7fw3>#+F<>2Ӽ%fϽZsMޢUqMhw7I9zJCf^ϽjHk_Lyw|8ƺ4=k [MՔFq#O~6wɫLO'2 M\3 d5%]hVbGeGRzll,fn id5gaɴY 4}7A9hMk>f)3.v;I>a==8j3.y r7k YSg=rXsisL sӞqْG9wnB3¯G8!s J3_cDٹjRkv~..XDK6mʼnU4Ҝe866VlXY7ޝИ'j+Gnm ~n֦NXsc yEvJ'<>N>gvhڜ[~wEPrM Q)i2|>U!G yK[om0Iتs7.+gon{ý՛5Mlz?2MP2GejਜyKiC}@Aqǎ03'fSW\qEEAEɯY-]&gfSs|>x !ʟ\8|1+ 3ے6R$h8BE'ߟͿt~n[b;}UW 2SII+1G_O<"'|䮪6OAXGfXQ؋_.+. 86hg 7'.Weee{kkk9 [)}{͵Z6eҷtkwfD25=k1#Lf/X~sPbu U;:I""}zbY X\ sisOYҝwɞ/_|ǎN#d-q#ל\ńՕ)|cϔ#|y?({ɧG`Ŀk xc>geSg.ꯏ-ޞXLMa,5Zv ixh9.\51< 9b 6\HK0;2 B[?w>ˢ䩹8E+)鋬v}m--F.fx~0[#7A8[v_0$$V"G8싯꺀F1*9+(ڹ=ׅEyvnCchÖqGX*p9f'ڿ}+o6>OmʷG{ 2fܘگ葑Qr%) ^64f/!)h 4GȞeI #?򧳋&`5X4"?rI*rGX aV\r~1}8UW?bqW H|WaJlah;{sIOfY5sNG)qĥ&.^23H+qƭ\sid/M7nl4YZ-X2)I ǟ|b][6 j˚4?>zhs6ϥ>-I SxxI<v2/zarmw#\vՃ>8¶lqᄘ#Ь4ga 7 1DZ%QMS'Mv©c#.杇XސGWh3rGH}^Is>W#/2IFkּ⫏<{#8d#d bxq~:{żM&#G6#߸moE۵9j&#OUWvn[X8Ba^G(~M[W)&(9r¹ݸu]а(b 7͞d΂_]gli\>KݿrEC/o 1=ɂgy~y  ?R2%NCYL"w#|:+fysSg_F !CL58ڢs 9sE8-Wj3/OzF;mVs[MUTKjjƜŴo \~O#dծW4<HMMTORҫ1*o AaD&\yujDŽ_s2j<1LpE&o/j# A5dn'p ѻZr=e7 i.eC8B,fjw_,\u[Qė߼ᦛKֲ!5}ܢXKs1Ps暌OU[ZY#<66\xn4k>Lߐ6 nKa'z*/5)8杝𚒓/8ib$|p9O]Yt*[W; .-;Zoo=J|Al&prT[ LT|:s:)6Q\ ;7Էs{scOJG,k`߷ѯ Gp-r¥e>`cdŹ_.0{ƽ46{|6m7.Yr]5jiHS02 $Z_|զ /'O^~Gs%/lv'75HQ̍[9˜XGƎ|\R?̞+qъ*OŋGDD1_ C3p|UrTk2sv.Z횾IOVS?1gі>}uwגX}rHUc5#_.[U2WBEViX(2 ;||Cw~ꌹGk=JǴY @qͤǚǣ DEs͍~ P\[[zq` eI(5 w`_T1Gp_sv}hU8]7}s?/<4;.r˦._<p~/d@Mśn}'tvnQ qyÝG8®KKr6lHoM9xG౉]/'Kto:5`B 9B1@?T5[.[xny#|.41GG^89AŲ&/p#Gdws#76^0̞E%ku7f>cO#4rf']WFaqʪ?qs r9Baa5`70GpA""oް wuoo=s#ٌX[~>%2CF\0$-\7L"fD#=y !;O(H޸a|f6XIoHrEIsO-~~'YqWD#~VIIIwh|u# B2[PY.]E?uǝ%d~{3/YuM7Ӎ CQOMLbÅKW{SJS|E{H~[*'v©~1q߬ݨgmLf(Ѱ!w#{|_}#ǵ.{E>o8i̐Ӄs HF#'>Eך-&#d#x^>>'2vxG8A\_4:@Kw&#.,йQSWrG#ƍߖo(9nLpFi!WmNMiƧs!+ī G5 A|e $#~.9A&F%#4`;Ɲ3qdxhEQmkFWp|8P\sr5s\Vq>9Rtt9arujUȩ+I|_p#܈ O|dpӞp~vɚP#k2+>6q8kbd&#(Q2sN]V衍bG@W87!p|*\$#H]d.ߜCT= əa#9N]5)#Gʒ0n1_! |bOxHFP G0)a#HWOdHFpk 0T*g2gGP٩m^sJ^`\s#p#+8>Ob d9P \ss>mVB=<8uȑA\qUz Xf'~5aщ~ p#܈ O|s HFP GkTߜϓ6TG&Fmb$\qUC9Baa?$n1_! |s HFG9i46Cc}hbdo2_APVd'9ŲAsn|' 'GtYTS2w6#HĨMKF#ԕzK5F'(y2Bvv6Ɓ|8~S;М||rȑdpNuCp1Mp>7bC#أ⠠  B9hg3a5?Ad41SW(#_F'h4t2leOWhΧ|r5gqPV%`VsQ F'(_,МOsOMH(86eAGۊdž_ޜo5Ad41*EG8JN]y_ X6A^y97bC!`hW#8ZAhgq.#x4M\kb$vUЉ,+;Gu9گn1_! |GѠNy,&hΧ|qSNMX2O%`]MP2rBkq's 4osG@s>e7epV7촊c;u%8Jp#! |bG(**np}>_A9x_OĈ&F KqPV%`Ŏ#XGFWp|8L"7sn9G0s4Sts>\ GO(Ї6|rVn8>Oh & FM|JoG :vMVqPV%`W%%p#܈ OG9Y,)) %%v~9)8:PVmd65W#p#+8>O^{ȸ8{91cPG@#'#(#"J2,%#G(,,+ 9Fov#' 5XSBBBXXj+*#/lp4Sns>N9)8:rPV%`%#G0"GFWp|8#9BFFFPPPgg' :|m'֭[WSS#;G@#E71;[J)+vԦMdb G܍p'v}MO}*..jMMMϫ3R6lذm۶#G 5;q8&UWWܹh}n|'C>ZP\\LAyur8pq˖- A 8}t CWWٳg=F#G[__yf;(j6mںu]ںiP[N:tݻkkk7n;)QUUU۶mkii<}4AI9!KRFW$#xO}LV 0`t"/4#xi 7b| >NxG?-111((G/pa:;{,m:={@Tkk+>ǎ30G /_Mi{{;HzW5u޽{)4vvvvwwDAޓ'O>|~p_}}NxUGDFF^{xq?!ЌFϣG+}tiw̙~n'&MiA3nEwi0{w J:qӧҝu!++|r#"FW;+;}"h~NM`0šţ9@>ѥ-!q_/JwM4E(618 JM{j1$q{H >Bhڴi*XUUjSSSzhr/G](&dr%rRd rWNp5ٯhrn|J >65#Q<Ǿ]F6?HE p(1G(,,3lp/q# ܈ r|XkPSSjʰiRAA}_s @IKJJpt:8AuA|.  <kp@q#@AXX}2l A jjj  [8XY0޻G G2F6h R1G0A$ GPG[iiFAaErQXAA^L>p Ax$@mrzɡAfe; HxBCCz{{q[  HPd MHJ8:7T  lkEQMp Hxs 8E  ۄXXXh#ОY7  Ar8w˦&kGA񨨨HYg#G n䄄.1GNJJJLL $G&5x8Am9yE!/ Lͥ!jEMM A$!G0I#,88A`##Sdd~ :tE:F #H|rej~ Am>#,)??F  go  o}"\^CdBIP7 AtGʲVg222!%%. 06Wg  hs <Kn___||| A$m<CmN8Mw   8~ b3 AI:@o ==]ח#_ArBk39\VUU1PVV AI9PYY/y \;!!!44#t:p 6ALlpϩQyyy9|x|d rw<#FiM_㾀#XG n68&k;z.={~:<H#"8K umpSXvC.\]gEWQ:s#:wﻌt:/p=tqzjm]-jp5ݢk]ٵ]uq߉^{zumt]LWVUsBW]Gf׮kp5#TUUEEEUTT^# fѯ( E/#2}2D&,p}8%"8 Da-fm @mAc!E MC96 G~quG8|Sz{{A8` .((Ap8iOp k9ɺM@{8}qeMF&s2*9®]u,!rwHXGRSSz}fffoo/n8AfG df,B;?TSd-r$#0P[[yA[9>F >$G] s s;Ϊ,^dM%#0y'O#@n @mwppdSB}eyd Rąj_#8pT!jݑ`#TTa$q7644#@s F1777((Heffvwwc!g8ŕA"p8yE!8d&#ʛG! -Τ9B# j1#8x98lݺ5555..nOi/Gp)g^#4A#_P9/}x㍋/~daP |AN\br:hnnOLL4LSN9# s"-nѝwWa_] /ֵY>:[G{]@>x4n;l[Y<AAKQ1ڋh(FN 0٤:''_~ѣFz?3%?ݐ#x9м m@7p"!zή.{Ml׳{Cj+{]7F_`Br%DК#xYpn^# D1 #[19ZsMJJԩɓmvʕ 8<ݐ#9Q.d#akY #vt F >u!EyA_4s)F j1`#^pU19Y,c\p9Q#80p@DQru`b#TX1*rްZyyySWW}TN: Gx9v\Ά{ bá^pbr]r833G111ζX,8_Dn`[Pob:#Tk7n(++NLLNJJ*)){qƑ'Lr #(5#x\pAk15 B1^]544|ᇫV1cFJJJ=z=mڴf8r'G[cL j-F^ ἺXoZ,Xݷoߴ삂j95rNCbu>9'''O<9//NzƑ'3^Ax *F8b)F G—ʸ6r#`A>!4x1#\0M6͝;7##_~[ֹA/Gف9B#|m1BsNuuu'ONNN6Lm۶ݻwZZZVV֪Uۧ95<*FВ#h)Fxӓ40y#22T#pOKK1#\:G;Æ ,Xʕ+(((;wnzzz޽M&MAIII#E#`A\z#sb&= |ퟦ4,݊gP$G8r OXԹY ~(‘q[,?pӦMVTfffFFuֶm[qA=#5_Wuv9gu>#(9 1[>d'xc]2Gh&Աsol`% ×-^dx,FwI%_O?hM/4GL~|PռUĮށ &s_Rͼe-+Z|_myͥ9zA]z.oߋ9v9޽{ΝۥKV*&ʕ+&M:o߾M6';;;333%%%))o߾hCn222~_/_jժR1Qr1GAW1W9Bm<(e܄mQ![/;_^8ldA_]M ~hyBm[W(hȚk:"M^[^ԐgnjXbz9F#9[w44{T#;eԿewQVYgdzkr{J1¶aԨQڵkePw,(k![D>H=z0# OL3dee,_D|ˁ޸q "GPk`G#`A\{#x]E1rǟ?Y9\>*$JQr5ߑOXRV):^/{_|mw''#Wn_dFKt21OxW3Nzb+9Bּܑi-'#fkC65nB0G(,,$G9y]ߜ=?حa~GkB]'n*ڼԱS>?}7;oᠵ17&)yHLLzB oto f1"iPr {}>%2Lw|mٛa]1MhZ'O,(3G r#1BrG9|9prSּ`]'n:rI ^à WKj֯ng8`mEJuVySCx<A=~9QVRإ7~qEw,Fp#HӦMH@r[{1 G9:DP?&G8r_M~2A Ad[9*D|-DP?aQr% 3]Pb9(G`#`:S5_b˫w[MC9Bm1:D9Ksr_YZC1##qA/#x΢!5)#Th+FP^-F G N1 G ls.h-F_T`#f390|p9ߊj-F*^ brr!Gyz<*F85H1a;##?Ggr#`:9,d#brq N^y#_p>U@@Cr #8|>!̊#@rG$#kp#|AKbA-F8b(F G* G r9i/Fh @1Bbu1N#x#L&r?#\ B1)c#s#l%G{Hr #x\.lNA#xZ@@Ay89!]1•#4j-FA#l%Gl6#נYbcA-FobC`3Z'4V95#_1*Gп29@9+F8brG_݃brAC¨bڋ979K:/r_^# D1 #Ti*Fx9>9ߋjZp0Ppm19r#or} -F j1BE##?G`G#9v\*F8b!\@@qA@,F1BU ]1yߋ#fr#`n-FAk-Fs19sk9#Τw9g#X[PkbZsT~rzrlszPpPplJ#_Dhu1ɠ#TSp9>pK:_r#j1# p19r#orx#Zb#4h,FP#y19r#/\ ;9BH#2F1:GпA#ݻ99dr#(vJpsΑ#ø G r/^z'NTUUٳ> cڵk׾}68"#hޭ:G醵r #xT/9Y9L&9@>pGsұyF/9 GIl6#^'} <5GXK GaY\ܺ"^t֯_Or$Gpvaǵ]"55uѢE~ڵkѭoTl۶MPTTty>ܞtq@s|r%z}7n={699بr#9#GHhѢAn:a„ѣGO2ߓsssǶWb?y755M:U>P9f̘q޽ukwܙ.0iҤ3gΈw_>{lNfffMM2>֯]V~/~ Ub&Gc{?f^Ev2łݻW#fb 5l׀MK4bU|2o矷X,K.; "u6uW^|-[KHx" Gr3g>\vKJJm6o޼Ν;+aJKKEW^QrW80++K;xbbbFF車^Xz뭸 gMݼyo4HA3//OԩSrbуyYZw w.>+:GK{~a3:+zzV[^6s_!w 5`1M׮]ŜvQǭ2b2l]gϞuM:|p||;#ӧO1sH5G0L>#4BN:q@Qs/#wrJѱoΜ9C#G=ztllK۴i3k,>>deٷo~oNfW~tұcǺ98\q)f7M"6mtLm'f.mz 8lz*:Ζ~b?-̙!'mZ AAW޹sgw---a PKtqt2L5X1ngeewQ0a#(=qDmO7C)ޑmhL9ot#8kFQb۶m111Ζ~&GsnDBpBg5k &G5#D` :u*mY[j%❸7ɚNjm߾GF޽/&oŬfܹSݰ/*=9s^vرCGtSj]666޲}pq\ŧ6Co}K>_^e}Xsg,Gp1MFF|GY4pMгgOe8XC~L>{Æ aʔ) G9豐#Df >sW#G8p *0`m^={Vjʕ.>^^^ >"JsonҥKĢ++Vnv6m $_[[+{עc/Kwԩr^zE{\a3D?YA97W+Ŷp#F9i&LC=b;[F[D#[.66VPp-VUQj" 9M9kHtujllt+-DS_477Wt]|f6mԾ8q)mo:W8[^-+S7:cٱ $~lcUTTxz ##rVnny֮]* #t׾@@ObӧO^^Kgr#`A>Ayt69|W[[nݺ+Vlܸu Zz:NDH /Zrva]bN}aǵ_!As 1T N M_-T[QՓlgBH\(I-Gh^Ӻz$_r59{F%#hti(w\uҭWϚ BB{h?BCdp7bгZ"$yl?5k90p /n޼d.z G ˗/O2رc.!š5k^~er#&9͛7]|||#GwUUU[C+M~o-Vo9 V GnrO[T|90dU8G J"d#@!(&Pݰ~ ܽnƮ́[Ձ|oz{hoCjbUqxn?^("i \w{ݞa-Hmnã6\̋)臡v8g[#Dt`(x:Tx@blsmƶͮ[vmsVuzy{hiλCUCY˟#.(!=ƀ\~uЇqYU6;K{tB\0mv{0COq9(5N G(B#0B"GZ#V>yoIENDB`dub-1.19.0/bin/000077500000000000000000000000001360435400500131245ustar00rootroot00000000000000dub-1.19.0/bin/libcurl.dll000066400000000000000000012530001360435400500152560ustar00rootroot00000000000000MZ@ !L!This program cannot be run in DOS mode. $PEL P# 2R@P$k Pc`$e\.textT02`P`.datatP6@`.rdata `8@`@.eh_fram0@0@.bssH@`.edatacP @0@.idata`@0.CRT,&@0.tls (@0.rsrc*@0.reloc$&0@0BS$#$ۣ,E)k(E)kt 1[Ã[ÐVST$$uy@)k)g)k@)k$ӃD$D$$0E)k  uѡ4E)k$O#[^ ud5g)kX9$փD$\$$0E)k u1ۡ4E)k4E)k4E)ku0E)k&)ktT$(D$T$T$ $Ѓ @)k[^ 14,E)k$s tA(E)k$` Ã9wt9v4$@"(E)k,E)k4E)k10E)k[^ fD$)k$)k4E)k!$!D$)k$)k!4E)k',҉\$Ӊ|$$ljl$(͉t$ \P(ku]@)kt|?l$D$<$ ƃ\$\P(kt$ |$$l$(,Ðt&Cw1l$\$<$3 1믍t&l$\$<$ ofl$D$<$h l$D$<$a l$D$<$ !l$\$<$. Ɖl$\$<$y D&l$\$<$ #l$D$<$& l$D$<$ zT$$A)ktL$(D$  &T$ T$ אpP(ktCU$`(kHg)ktD$`(k$Lg)k…t $pP(kfU]ÐUSEt4Ct$LP(kCCt$-C1[]Í&'USEt4Ct$LP(kCCt$C1[]Í&'UWVS,U$jlD$ D$$D$$Ft$LP(kFFt$.F/ɉ}t-UE ЃJt/u\ЃJuUD$$U~F tE 1,[^_]Ãu拃D$@`(k$D$ UD$D$%$`%G}FW|t :4WG:U#D$ $U@P(kt <$LP(kUI'UWVSMu  $d` $ M @xxED$ $g)kDEЋUDž\hE܅ɉl1|tt\3M MUD$T$$x}5Hh)kptt0Xˍt&É$օu-u }u⋝XED$D$<$M9M!уtn+ptMA(pQ,tyC\mu}ԉ!MA(A,x;lD$a(k$,$[^_]Ë1D$\$X|]Mۉhl<|%t{tM %d D$T$$x"!tT$D$4$AEEMUT$D$@ $}|p t799)ȋ|1ۉppx\$L$$91]UMU4$L$T$\M $*xT$Tt&S,C(ptp tq\ t/xD$ t$|$ $$11 11D$$up}t?|D$L$x $ ƄEM)ϋ|D$ D$L$M $ФUM$T$L$M $g*MT $IT*Dt&Dž\DžhDžl;hEb\1Ʌ@&lh $D$`(kT$D$ D$@Լ|D$ D$L$M $ϣMD$ D$`(kD$ $袣ED$E܉$EuUD$`(k<(kNlEMT$L(kU|$L$$MD$ T$D$?L$ ML$| $|D$ D$L$M $l$T$hTD$#Tp)dždž0`d$D$T$Bh&v1| ?4$|$^xhl4$T$L$g3 tZMptD$`(k$| hl)ptt&pt$D$T$v@D$$1:pt؃D$V`(k4$D$+ET$T*E7ED$x$g)kuEЋUԉx$0D$p`(k4$D$蚟iUSXg)kMbi)Éi[] UMbEM +E+MSi)ʍ[]ÍvUS UE] M9t))ˉUE]E5a(k [])ˉ]E5a(k []Í&UE]ÐUWV1S,zE1Au sv8tla(kutZ=D9uɉ%$tUBƉ$tUB4$tU,[^_]f몉'UWVSE܋U D$ ET$D$E$膸t{KtD$D$$!U E|$$T$D$ S҉EtD$$ME؅t1/<$G E]܅tUE؉D$$uًE1҅‰&UESEx []t&[]Ð&U]]uu CtD$D$$/nuFt2Ct]uE ]]cv]u]Í$V 4$LP(k빍t&'UE xtÉD$E$KÍt&UD$ &$kD$@&kD$&k$\Ít&UED$0,$kD$$_ US]$$_C[]ÐUWVSLE\ucXt8-tꍕt$T$ \$D$Fb(k$u4$D$ K$‹EHt$D$D$$6T$UD$$]$LP(k$QUJtD$$'Ut$\$D$ D$sb(k$DU1ǂ\L[^_]ËD$Xb(kD$E$eU\$D$ $D$B$딐UXu։}ω]ED$D$ 4$|$5ӉE~~D$QD$ 4$|$ӉEE\$D$b(kD$ D$ E$۪]u}]| rE--:-@-:--@| cwie+MD$<D$ ׉4$|$o\$D$b(kD$ kĉT$D$)D$ET$ D$ E$']u}]| = iˀe+MD$D$ $T$\$D$b(kD$ D$ET$D$ E$謩]u}] U8]ˉuƉ}~] )'\t$ |$$D$b(kD$$؋u]}]Ðt&|pwt$ |$$D$b(kD$ߨ؋u]}]=D=?f(|=?v%D$D$ $D$\t$ |$$D$b(kD$D$T$4؋u]}]Ðt&t$ |$D$b(kD$$؋u]}]Ðt$ |$D$b(kD$$ȧƍ t$ |$$D$b(kD$虧؋u]}]É%?D$fffD$ $D$\t$ |$D$b(kD$$D$T$4/t$ |$D$b(kD$$vUEݐǀpݐ`ǀtݐǀxݘǀ|]Í&U(uu ]]}V w1$c(k$T$t$|$ ݛt&]u}]Ív ]u}]f$T$t$|$ @ݛ]u}]Ë$T$t$|$ ݛ]u}]Ë$T$t$|$ ݛ]u}]Í&$T$t$|$ ݛ]u}]Ë$T$t$|$ mݛ]u}]É]u}]ÐUS]ǃh[]Ít&'UME U]ÍUME U]ÍUUEM ҉tpx @]Ã]fUUEM ҉|xx  ]Ã]fUWVS,E0h+`E+EEE5Dd(kptݖ߭p}E fElm߽PmTPh߭hm߽XmX\19hRغ*h)R)‹l;tLhL¦D `L|D hh1҃~Ⱥ*)R)‹<8ݝ(<$$\$ `L$\$`$݅(DLL\ + x|߭x}E5Hd(k}E fEm߾muLf߮\$߮x\$߮\$ ߮p\$$҅t]؍؁,1[^_]-ptj7A/i|$ݝ(L$ ډ$T$݅(#f}E fEm߽PmTPlh߭hD?t&\;TX;Pzt&ÀuG D$lc(k(ݝ($葺ˀ݅( #x|ݝ(T$D$ $|$$$`݅(d $ݝ(D$dD$ |$cD$T$ $T$C8݅(<;pB4$D$(c(k(e(,[^_]Ít&PTuDž`DždDž8Dž<@ptݝ(T$D$ $|$pX݅(pݝ(D$dD$ |$$$D$T$ $T$$@݅(D!J11Dž@DžD}ptE fEdm߽hm9`dptt+pt+hlEp}tlEh Nx|pthl@pt`dptӉtlph`dt1ptD$dD$ $T$$+$\$ $D$T$ hlMދaMԉ`GMʉX-MPMLtMËp`ML$MA$C$Y$G<DEE]8w -Ot G +G ƒ W$ƒ t GRW u 9}kWG G GW y$d(kI q jrI 1uUEuVq4I @uUEu%A4A Au9wAt&uEuQ8\A8uErQwA /$MDP(kD$@$@P(kMp@ QI AA7 wAjfQ M$DP(kMA I AQt?M$DP(kMAAUEu]t&Gtt$LP(kGGtG t$LP(kG GGtGt$LP(kGGw0tG,t$LP(kG,G0<cƒ00$t$t1fO t$G$Ot$GۋD$`d(kG $DžEt G D$e(kD$E$i} MG ftsB,|$D$le(kt$D$ $ 1B}G G,υ vU\ WVS`)čD$ED$ $D$D$u^t>GvPW MT$GD$E $ы9?u $1\ [^_]f}DžDžDžD$E \$$9utK ڍ= v͋t$ $}\ [^_]Ë?$T=USÃ@ t $LP(kCt $LP(kC t $LP(kCt $LP(kCt $LP(kC,t $LP(kC(t $LP(k$LP(k[]Ð&Uf(kWf(kVS\HpXDʋPu܋p ]؋X$UP0Һf(kDf(kEօۉUЋPtEf(k:.EԶf(kuҾf(kEf(kDEԠf(k@8f(k]܉L$(M؉T$ Uԅf(kDE\$ ]Љ|$t$D$$E\$L$T$D$$f(k/\[^_]úf(kU($]ӉuƉ}$9v]1u}])É\$4$H]u}]ÍvUVSE 0E@ t/$gV ҉t'$V9r9҃[^]ËV 1ۅu1t&'UWVSl]$D$@$@P(k}Džf(k ;#tdD$ $tD$ $t$T$D$g(kvtD$:1$Ftn$LP(kDžl[^_]ÃDžD$D$g(k$YOw$g(kDžD$f(k$\A0닾f(ktf(k $f(kDP(kA ЃD$f(k$DžA$1;.É$DP(kBt6Dž&$DP(kAuʍT$D$g(k$ Dž"$DP(kBtDž D$ D$$DžAQ @8($f(kDP(kAPBU Bu RM B4FD$C$tCV^T$$JS /F 4D$$ p4C$LP(kCt $LP(kCt $LP(kC t $LP(kC t $LP(kC(t $LP(kC,t $LP(kދACACA C ACACACACA C A$C$A(C(A,C,A0C0A4C4A8C8A.BEޅt $LP(k$DP(kAA$yT$$g(ktl@8M$DP(kB K|< '< _v f=fEt$D$Tg(k$T^DžU T$$g(kUA(t $LP(k4$DP(kB(euED$?$B9M+ED$/D$ $+]C$sPP(kB pMt$$L$(B Dw11< t&Mt$D$ g(k $$]DžL$$g(k/B,t $LP(k4$DP(kA,1Ҁ8"D$ D$Љ$mBJUD$/$.D$$g(ktjB t $LP(k4$DP(kA D$<$}É ؋@@eHT$DP(kA4$DP(kBR$LP(kDžxHXD$;<@@'UWVS$t&9D9t7U=U؃j tH Htօۉlju2[^_]Ít&ǍUVSut3Ft $LP(kt ۉuuLP(k[^][^]Í&UWVS,E`tZX tStM1'D$<$}4$ELP(kEtDžtủ<$1,[^_]Ív,1[^_]ÍUWVS,E uE䋆|PXt4$ND$D$4$Y`|tC u7}tF`t;Pt$uE ,[^_](Y|$$g(k g)kE EED$D$$ h(kD$ }u'D$D$h(k<$E4$LP(kűED$h(ku؉$E܅|D$h(k4$D$St&EtXt$džXD$D$4$Wu؋E܅E$fD$ h(k<$EaEE$EU#Pu6uuW uBub@@1f@A]@A]Í@ f@A]@멍'U]1ۉutE~= tHutu3tt2<؋u]]ËutԋuÍ&'UE0E ]Ð&US]E D$$D$?t ǃ[]Ít&'U8U]1ۉu}r rtJM ]1ɃzX1 ދBz ~7B\$UD$E$访UZ)rz ؋u]}]ÍvJD$UL$M $qUBTrPZ tBB zHB@MrzBD؃BXBPBT]u}]BB ]u}]91ivUWVS,:u :tuÀ=Hh)ku&t $ׅuD$ $EtY9=Hh)kr 9t $ׅu)ލF$~PP(ktU|$\$$E@UD2,[^_]D$ $ֽuD$$w1v'U8uƉ]}E HM܋Q(I,UME11;Mdž}tCt&(EtREtD} t> t9džCCU Uti4$聞]u}]Ít&Љ+EU|!+uvudžD$h(k$Nf]1u}]Ðt1t~tAdž;UE܋PH !ȃEptE!ȃdt$1ɉE!ȃ|e2D$T$ D$h(k$Mt&=t&t&'U8}}]u7<$Mۉ<htoC\t!E$LP(kE$LP(kC\HtktRE u7Eu)uFHNLC S$)ڃ~kE E ]u}]Ít&C S$C(S,F8V<뚋C S$C(S,F8V<$BC8u$wC8av|wD$,i(k4$FE 4y'U1U4A@tMtdttt&]Ë0U ]Ë0U ]Ív'U8]ӉuΉ}NjBX9=v1D$D$Di(k<$ F]u}]Í&@ҋKT9CЋT$U)M$HP(kUMtLȉCTS`t$$T$8CTsXCT]1u}]ËCTˍD$ti(k<$`ERUWVSÃu 2[t+34$蔸|$4$D$ܹtۃ[^_]É|$D$$i(k賹[^_]ÍvB>u UD$L$$i(krɅÐ&U(]]}} u3ǃptjtR8@@t1ptZD$$}u]u}]Ð1]u}]Ë]1u}]É$d,t։} u]}]]7&UWVSu 4$4NjEu +[t$|$t$$bt[^_]Ít&1[^_]ÍUX]ӉuƉ}8BptC1]u}]ËE uC ̋tD$i(k<$#uً HEEEȋMЉD$Eȍ $D$i(kD$@D$ ỦMH\Mԉ $MỦL$ML$ Mԉ$D$L$y)U MЋt$LP(kUUM i(kT$$i(kɹi(kDD$tMЉE$LP(kUиC i(kU 4$T$4i(kE tM i(kDƾi(kD$t$<$L$ D$j(k{FS 1u}C]1]Ëi(kDƾi(k뱋EL$M 4$D$ L$Ri(knD$i(k<$LTEEMЉEȋ &U(uu]}Bcv%<t*u]}Ѓ]1]u}]Ë1t5tt#+ Iu ǃ<1t=tt%+$uǃ<t& t$LP(kǃH$DP(kHtf)D$8j(k$D$?+utHtH$DP(kt+ǃw&adZU8uE u}U]}E䋆 tu$t(u(ǃ0t"ut}M䍓 E ]}u]Nǃ1ǃ0]u}]9aM䍓$D$<$HH‹$T$輱Xǃ뜐&UWVS,E} }EEuE Hh)ku t $ӅuHh)ktyD$|$$i(kѱtmEFN u t <,u<,u t$Ӆuuf,1[^_]ÍD$|$$i(kHtYFED$j(k$GA|f1} |$D$E$-uMEǀ<ED$|$$i(kӰ%EN~FED$`j(k$@Eǀ<E1N} |$D$E$FuuE$' UD$ $@P(kÍvUWVSLM] U 0MԋMIMЋ4}A@MԍE|$ D$T$L$$6ME+E9G)‰E̋)1F(V,U 9M2UȉV@EԋFVDVFPEЉVHV )ȋMVTUǃ`t$kFVF N\FXL[^_]ǃxUt $LP(kM $LP(kL[^_]ÍMԿ@}@F}E$L$|$UuUEEvM̉\$D$$L$ MԉUȉL$7UȋMuAU 9MC7aUFX7;&EẺT$ \$D$D$$l7MUgU8]]uu}S9Ћs.t$LP(k$LP(k]u}]Åt K<9v?xx 6щM 9Mr<tI|$$HP(kt/S{‹E t$$D$ 1s]u}]ËTf<$PP(k빐t&UVS uED$E $Skt.$}\$4$D$$ELP(kE [^]Ët $LP(k4$LP(k [^]Ít&'UWVS} ]<$|$$D$W=Hh)ku t $ׅuD$ $質tWƋE)މ$谪9Ɖs 09w&E|$$D$t߃[^_]f1[^_]ÍD$ $HuD$$4냍v'U(]É}ωuLǀxt 1tM t t=t t4D$j(k$t4D$j(kD$j(k$x1]u}]Í&D$j(k<$uǃxUWVS,UHh)k]D$:$U>x@u$ӅuU`t$UD$$j(kT$Ou{UUHUUlt$UD$ $j(kT$u'UUT$U D$ k(k$ut&v 1,[^_]ËUD$;$@tԍx@tTu} t;$ׅuu맋UD$$j(kT$\U'u;kG:D$AUD$ $j(kT$9U UWVS|]EĉD$D$aU܋M؋ED$$k(kzlҋUċ(kL$D$?T$$UȉD$ENjL(kT$ Ủ4$D$ T$UЉT$7M@t$t;tE D$Gk(k$0|[^_]ËE D$yk(k$|[^_]ËU D$_k(k$|[^_]f$D$k(kE3E|[^_]fUWVSuE EEE}UȋH4$UE u0t $LP(k$DP(kxE@ @$@(@,4@<^rD$k(k$ItLt$LP(kdžLUD$ |$4$T$EDEudž\t$LP(kdž\PtD$k(k$# dž\xtD$l(k$x ED$l(k$YD$.l(k$AD$Hl(k$)sD$l(kD$Hl(k$)Ei(k`t$LP(kdž`D$j(k$t4-D$U$萤U8@<t f t fP~ L$i(kk(k$l(kҺk(kDET$ UD$T$b`EEЁĬ[^_]Ë DEEk(k{Ek(kg<s(k[t&4E_<[ $D$:U菢UtdtU$LP(kUddž`M9\ HT$U $M艢U$E UЉ$EUȉ$EUETE)‰$PP(kMEc+Uȉ$UT$UȉT$UEET$$T$ǡEEEЋMU$E)ȍDM+EL$D$虡LtHt $LP(kEǃLHEȋUD$$l(kT$ktwlt-UD$l(k$Z Pt x t6 ҃U,t&dž$LP(k$fE}3D$l(k$/1҅k(kDЋẺPEw( tt'E1D$Am(k$! LEk(kt* t rt eD$ $@P(kE?|$D$m(k$E'EUȉ$pMȉL$D$E$EЋEЅEi(ktP\i(kE‰EȋEi(kt8tPi(kEEli(kU̅DJ}Ћ`DȅDN:EtLE‰EEi(ktXEi(kEEETi(kDЋHL$$M|$ }T$UEi(kEEL$|$EET$ D$m(kD$8ED$4EȉD$0ED$,EЉD$(ED$E߉D$E$:EЋTt $LP(kEdžTX`D$D$$Y34d@K|Kt+KxdClC|Chu {p< @QA< dcC`ChE  u T$)׉4$|$ D$CHddCHCƉCLEC`ESC!T$D$$躊CSC(S, U1L[^_]< ChPShDuH[D$ L$$j(kӉu  Y u9u t5D$fq(kD$m(k$    D$fq(kD$[l(k$} LJCpD$ t$u D$4$CpCH}CpClst>1} 4@<BC`L[^_]ËC#CC`bTu C 64@>&HD$o(k$@džǃ,CCC(C,C(S, |MxE |$ D$Cx$D$D$L[^_]ËE 4 } |$CpD$ D$$D$U $b_ +M JD$p(k$. 8t $LP(kRD$L$$n(kxzt&D$+q(kD$[l(k$u džD$q(k$/E |$D$]p(k $D$ ED$荄Eu u t܆ɉttK~C H}  ~u udž|$0E 6t&SC>t&D$ D$$Ƌ t[9|W~KD$p(k?$5D$+q(kD$m(k$iq9w"sSs(S,t$T$$\&} 9QF@t ǃCCC(C,ǃD$$Hl(kD$r=Hh)ktˆỦ$U̅ua,t\D$t$$l(k$uED$t$$q(kt6ǃt댃뀋E ǃ$裳롐D$t$$q(k訂tǃ7fD$t$$q(kxǃD$E D$wp(k $D$ ED$Eu dž E$LP(k|$D$mp(k$萀} LJ ǃLJ M E HD$0p(k$gU ǂxǃPD$p(k$ LJD$t$$q(kӀǃ^D$$q(kD$蛀 p@uftHh)k$҅uD$t$$q(k?ǃD$t$$q(knǃ} LJt$T$ D$p(k$} LJD$8q(k$k} LJD$lq(k$ID$$Am(kD$j"BRJЀ wJЀ vuD$ D$$z33 ǃf؋UCh{p} ؋4C`Cdnt&u A} 0D$8j(k$D$ `t&D$ $q(kD$~vD$$ r(kD$}@u$}||$E䋃$/҉XMD$t$$q(kt}EǃUC`Cdp(kuuD$ Ủ4${U̅xpD$ 4$|{Ǹ t$D$p(k$EË~tD$ t$$q(k|;ǃ T$D$8j(k$D$$r(kD$4|t(D$$,r(kD$|t =-,c#} 4@><$D$zqMCd9tD$D$$u dT$D$D$ D$ `$D$輡D$$D$t$$q(k{ǃu D$T$4$ǃD$ $@r(kD$zn8$DP(kE +D$t$$q(kzD$t$$q(kytOǃD$ 4$ixU̅\ D$LP(kbD$ t$$q(kyuAU8]Éut,,L$T$$t$ut$ ЉƉ]u]1w틃(D$D$MD$ Rs(k$x(MD$D$ E $D$w]u]É'UVS0EU u]E94t$u$҉t$ uJPT$t$T‰1x0[^]ËU7tQt 0[^]Ð00[^]ÐUED$ D$E D$E$Li)ktU1Í&i)kɉ¸Q3'8EÍvUWVS<]uE8@$E 94)9}F}UT$@}@FUHPT$ D$$T$|$D$E$vRE 1ҹ@94}‹|$T$$D;EOEJPD$ ED$x ><[1^_]ËE<[^_]ËE|$T$$u1ǃ><[^_]Ív'Uuu]E}U  s(ks(ktsHD$L$T$ D$ s(kD$<$!Ӂ tډÀDڍPDۃ1)$7uvEMU $]u}]UWVSLE 8ED$E$3E$Esuԉ E9td)ƍED$E\$ t$D$E $Nu9tċE t$D$<$D$EMЉD$ iEM9uEԉMЉ$LP(kMЃL[^_]ÍvUVS ]ED$ E D$@4$D$!20t tUt/4$s=?v'D$D$ t$D$$ [^]Ƅ Ƅĉt$ D$+s(kD$$ǃU8uuE}} ]u E$rt98;]u}]uj @iT$ Ut$D$$=9$D$Qs(k]u}]Åt8t$D$D$ E$=9]t$ D$$D$0s(k+]u}]É4$PP(kǸMt$<$L$qǃ]1u}]Ð|$$HP(k¸Mt$UЉL$$qU1gft4$PP(k¸=M$t$UL$pU1 U(Euu]}D$ED$ D$E 0$Li)kËEt؋u]}]Ívi)k=3'tB4$D$%D$gs(kD$$_E8؋u]}]ËEQ뒍t&U(Euu]}D$ED$ D$E 0$Xi)kËEt؋u]}]Ívi)k=3'tB4$D$eD$xs(kD$$E7؋u]}]ËE1QfU8UET$UT$ UT$U 94$҉T$UEÍ'U8]]utVtLED$ E D$4$D$,-4$D$/4$zRkD$$@P(k‰,t)$U蘵D$ t$D$$~U,iǃ0wt >ǃ8Uԋ t8P1ǃDUԍED$ D$D$$81}t$AQ$A)NjP}$&Q$&;E4$LP(kL1[^_]ËUЋ*>!4$P|/UD$ D$t$$>8Eǃ0D$P4$D$bZ=UD$w(k$ǃD,$hw(kDP(k08U-Uȋz RUD$tw(k$ylUD$jw(k$\EG4$LP(kE,EUD$jw(k$v'UVSut teǃD$w(k$O@$Ndž fKL$ D$x(k$D$ $(y(ktFdždždD$t$D$ D$D$ $!8t!t$D$D$ D$D$ $=D$t$D$ D$L$fD$ x(k$:,: : fF@D$ D$t(kD$0$D$L$$:D$x(kD$L$D$ $WD$t(kD$0 $D$ 43D$hx(kD$0 $D$D$D$D$ D$t(kD$0 $D$ }L$4$衾\$ D$x(k$D$\$4$\L1󫋅L$D$4$D$ N,&'U(]ۃuAƉ}:Tt:ÉD$D$Hy(k$mu dT]u}]Éd]ʋu}]&U]utD8t:TɃA9t C ]u]]u]@USÃu @t88t.D$D$Py(k$}u ǃd[]Ã[]-'UWVS, E2 džXtfX~1 t&tO[9utA8* dž\D$D$t(k$迏ud,[^_]à DU1dž\`0,džXD$D$Xy(k$ cdždTXw ($dž\&,[1^_],1[^_]ËUZ u?!ÃtfT$D$ $C,[^_]džd1(džX,[^_]a8D$du(kD$$Ddžd5v'USÃR u`uv,8 T$uZD$~y(k$~u ǃd1[]ǃd [ ][1]ZD$qy(k뤃[]t&tT$D$iy(kydy(k_y(kD؍&'USÃ@ t<8t2D$D$y(k$蠌u ǃd[]Ã[]USÃx t []뀋8tD$D$du(k$<u ǃd[]Ð&U8uƉ]}tJtV t 1t]u}]Í&]u}]v]u}]/s(k1ȋL$ D$T$$y(kqtSD$D$t(k$QtE<$LP(kEE$LP(kE3džd$t <$LP(k R?ID$/<$>1<$DP(kt$E>M|/t $D$/>Mt@ϸy(kdy(kۻ_y(kD&'UWVSL] }E0UЋUrUE^4$օR=LЋt}~ET$ UD$D$$u$?tL*[^_]ËV,E܋ U̍UT$UЉD$ t$Mĉ$褉UMā܆tnE܅uOUԋDЉUԋUi)kUD$y(k$D$s8L[^_]ÍE뼍&D$y(k $ U̸ǂdǃL[^_]Í}t&1ދUD$y(k$fUHu։}lj]0Eԋ4EЉD$y(k$EE̅tGt=83~8D$Tz(k$UED$E|$$ ]u}]ËED$ D$D$Eԉ$tv1ttD$z(k$ED$E|$$*1}D{t&$D$z(k] u}]É$D$z(k] u}]D$z(k$EYEt&'UWVS,D${(kE$D$$*:KE.u_udpu{LωL$ D$D$$yD$z(k$ ,[^_]ÍvEuE,[^_]Ut&~T$$EGED$`$E/E럍v'U]]u}E0Uulut$ ut$L$$UMUƋE=܆MtIutd!vfǃd]u}]É $ň]}Ɖu]Ít&D$y(k$[LJd]u}]f$(k=;ǃh!UdMYD$@(k<$ǃL: }Mt =B u1 BRMI(MMq,9 | 9E   MEqAD$t$ D$ (k $6 EMhtpUW}LMD$@(k $ǃdǃL ‰3= UTD$D$~(k$= X D$~(k $d=^! 3=uS   u؉7v8 c=tD$D$@~(k $;=EM$PP(kME U"W ׁǑUu x@ <"u" "G=D$$ JG-cU10hu8tD$D$ |(k $[ǃduPC0D$|(k $E‰D$ǃd-cHtX U D$|(k$ǃHS=~\/1҉?,==EM$PP(kME= EU u8 t8UtU}uED$|(kM$=M xt $LP(kExW;=u=&D$x}(k<$1@t-D9 Ɛ=]D$ D${(k$u=N==2`M0B@v=UD$D$D{(k$ J8cv`r҉`9X,ǃdDD$D$Xy(k $V~=K18c\=LXtpD$CD${(k$Q=B ǃdfU@0Q(Xǃ\B;0X, =^nD$~(k$賽D$~(k $~ǃH:D$D$}(k<$ZǃdD$$~(k $6ugD$}(k<$ED$ED$ED$ED$ED$ ED$D$ }(k$U008UĉT$$Eԋu܋MD$D}(k(kVlL$MD$E‹UċL(k $D$?T$$UȉD$ T$ ỦT$UЉT$uD$ D$$t$蚼D$D$|(k$谻M D$D$|(k $菻BRu0uPgǃ`4ǃ\ǃXXD${(k $ă(kD$z:ǃd+}cMt Mt$ uD$ (kEL$4$UyEUE֋EMt$ D$!(kD$ $PFs(kD${(k $D‰D$y{ǃdlD$$hZǃh߿E9+D$D$$)щ!ȃt[uT$ L$D$u~(kƌ4$D$@UMt$D$ D$$UML$MT$ $X.nD$D${(k $xBǃd3D$ ~(k<$追'Ɛ9D$}(k1<$葽MA LJǃduD$D$i(kE4$tE=&8D$t(k $D$w|ǃd mED$ D$D$$EAcceEpt-rEangeEs: bEytesE 蠸D$~(k $衼ǃdt$D$t(k $>wǀpǃd`X\Xă(kD$D${(k $v?uT$L$U4$ME,U؋M(UD$$|(k$>ӼvMt$ uD$ (kEL$4$U觻EUEj\t,ǃ\DD$|(k $D$"vǃd N U0D$D$|{(k$'fE$LP(kUD$g|(k$8$u(MD$$}(kD$@ $EED$ ED$ED$ED$ED$ED$ GUt$$8x(t $LP(kEU(D$D$S|(k$*(Mlpǃ\ǃXD$}(k1<$UB LJǃd,| 1MD$(k $M(Mptr)ȃt:B<(G0 wSB)ʉ(*0 w39ȉuND$D$ $h$D${(kC$$cD$D$|(k $sxt $LP(kEǃd xE8/ID$D$N|(k $NsuY(t $LP(kEU(D$D$S|(k$U(Mlǃd NE$LP(k&'Uh]]uE }E31tBpta u w Lu U ]u}]ÍE܉D$D$$AsM܅tՃpudtU $T$uLutt&L #fp.+fD$D$D$D$D$D$ D$$E-LE&GG MԅUD$T$$!ŰUE t;uЉΉ]ĉӉ Hh)k‰$хu<-u]3u׉ڋuЋ]čED$D$$(!M9M !уM̅7+EŨMԉA(EȉQ,Ủǃ<MA(A,t)G _iF8t͋@~vUFiE|ǃLE1E $D$QM̅MԋEȋỦEȋU؃t&'UH]Å҉u}u+ udǃǃ@1]u}]ÍED$$ t#4tщD$$`ǃ4빋O tD$D$D$D$D$D$ D$$*at&U]] uu\$4$uu ]u]Ë]1ҋu]UWVS,]E ǃL$Eo/u)3 t-}+}u,[^_]Í9u3FFD$D$4$"D$D$4$"D$D$4$"D$D$4$"ǃ@t @ E pNjE}E0,[^_]bf$x(k(t ؆$Ћ̆D$$T$xq̆x Ѓ3pІ}l$BЃ3I`:̆8$‹U܉$U܍D$PP(kĆ$U܉D$U܉D$$U܋t $LP(kǀU܉D$8(kD$$q$t.̆R T$؆<$T$Ѓ6FGdž3ІPH8@@dž$OĂ@ E}NdžD$/} $M5M؅x-@U܉$DP(kȆU~BD$ $@P(kE=@M؅?ІdžԆ$k؉MGM؅iȆtU܉$LP(kdžȆU܋ІU܉$ԆdžԆdžІU܃#pE$D$Odž3/džҸ늋}XI1ҸD$T(kD$$٭dž309t $MDP(kȆMtVȆtƉ$LP(kdžȆU܉M؉$DP(kĆU܋MAǀ0W&k8A8D$(kU܉$U܃3t&ǀȆtM؉$LP(kdžȆM؉ $LP(k Ȇt$LP(kdžȆІ$ԆdžԆdžІ}}B8@tBRb̆D$$T$k̆x džt&'UWVSLuED$ E D$<$D$ !%tDSD)f @Dž9tv)׍D$\$ |$04$D$.uHtt$|$D$T$ $D9ut&L[^_]ÍvUWVSlu}ЋɉMc} N } dž@džHdžPtU$LP(kU T$D$ D$$48/$UUEȉ$UxHҋU+Et|tsMȉP~(t8t؆U $ЋUdždž8t8E_t ǂ|$Zs|$D$4$$auȃ,[^_]Ð&USÃ$ׇD$$D$$4t D$$M0t D$$Mt$LP(kǃt$LP(kǃ t$LP(kǃ t$LP(kǃHt$LP(kǃHLt$LP(kǃLTt$LP(kǃTPt$LP(kǃPlt$LP(kǃlXt$LP(kǃX\t$LP(kǃ\`t$LP(kǃ`dt$LP(kǃdht$LP(kǃht$LP(kǃCxt$LP(kCxt$LP(kǃt$LP(kǃD$$?_D$$)_D$$_D$$^ǃǃǃǃt$LP(kǃ$$LP(k[]Ít&'UWVS$(kD$ t]1<.);Mv:_9]v&}9v$(kD$z u녃<1[^_]fE܋U؉L$M)‰T$$U UЋMԅt;Mtz.uE؉$* Ev'UVS1ۃuvpt$LP(kDŽp&uًTtPt $LP(kdžTdžP[^]ÐU庘WVS ] }((}puTuh1tft1&tMpptރ [^_]ËEǁqƀptf닍t&'UVSUE uT~ =ND$ $@P(ktD$4$@P(kts[^]Å 뷉$1LP(kfUVSutRt5N~1f9^$LP(kFLP(ku[^][^]Ð&US]g)kCX4(kP C@SCdP4(kChClC@ǃǃǃǃǃǃCHCLC0ǃ ǃǃǃǃǃǃl<ǃTC 8ǃhC$C(ǃǃ0ǃ4ǃ0ǃ`ǃ<ǃ@ǃǃ$(k2ǃǃǃǃǃ<ǃ<[]Ít&'U(D$]u}$@P(kǀ|@$~$PP(k$($ǃǃǃǃǃǃ̆ǃ,u4E]u}]Ív$LP(k]u}]ÿ@$5~t $LP(k$$LP(k뛍'UEP1t$6iÍUVS]3C8tD$4$C84$At džt$LP(kdž4@0t U $T$ЋC4t*D$D$(k4$dtt S4D$$4$uRdž4$W1[^]Ë$dž0(dž<$踅-v@0 1l&'UWVSÃ,ƋtH1҉]܉EE tU9X~P tQ0u䋁 $4$|$D$T$ ;E~]EU܃tut&}]t,UD$$tUE,[^_]E썴&UWVS,tH01ۋuY&tK9uUUtht@\$D$ (k<$D$ -UZ4B0Z4B0t t:,[^_]tB41B0D$D(k<$UӓUB4B0UWVS|H+D$$@P(kǀ4(kǀ0ǀ4@4ǀǀ(,8ǃv11$(X\<Bt$?dt$!%k1Q$!%kQ$!%k Q$!%kP҉t$DP(kn|xfC(C,H$=PCt$LP(kǀǀ4$PP(k4$PP(kCxT$D$(kt$ H$+Rt$D$(kD$ D$H$Dž. D$@<$D$? $Dž<$4$st$D$D$F|$$L$u/t&4@@D$(k4$8t-D$xt$$(k ǃD$@<$T$ L$D$(k<$ƅX t$LP(kǃ D$ D$|$$苜 t$LP(kǃD$ D$T$$8ǃ?[\D$:<$ZD$ D$$<$DP(k)4$LP(k4ǃǃf//t&D$y(k<$Z>/LD$/4$t&1/lj<$x|$4$D$DžDžy(kt&D$ D$L$$訚#$=<$LP(kaT$D$ (k<$/HD$$i(kD$LtHt$LP(kHLJL81?󫍽DžDž?󫍍tD$D$ $yƅtD$D$$HED$ D$T$$$ D$ D$T$$`D$(k$D$GD$ $:]D$(k$oz4$LP(k&1<$+4$t$D$F$/jt$ D$Å(kD$H$tRD$$(kD$DžDž(kfD$$(kD$dDž(k6D$$(kD$4Dž~(kD$$(kD$Dž(kDž(kE&|}:/<D$/$4t4OWׄtOˉ֍&Ë Ph)k$хu:t%t .uЋNjD$(k$'P8D$t$$(kqǃD$|$$+4@<uuǃ4r(kr(kǃ<$D$Ѕ(k}T$$Pǃ4D$|$$P D$q(k$}D$|$$R~/V1T$4$щL$>/~&!$<$T$D$QɋOKpGD$:$ƋH_QftB1Dž tBAuDD$ D$0(kD$ <$=(k(kDƒ(k(k|$ D$t$ L$|$D$T$8$9(kD$衭lLtHt $LP(kHǀLt!D$D$$}ƅt!D$D$$Lƅǃ4@@ t$DP(kf$DP(kZL`dhlptxP|$$记 i3ǃǃ~džx Hu džH4$~IG8WD$D$4$gD$D$4$/<hD$D$$$* N~D$ D$<$9:=D$D$O(k$fw$(k赌} ur40th)k$҈u捍_profGxyG $E >u$(k* t$LP(kD$t$$(kBaǃ4D$ D$D$$MǃǃǃD$]$M@~:D ى]Yǃ$(kDP(kt$(kDP(kqD$D$D$D$D$D$ D$$D$t$$Ɇ(kǃD$l(kD$$y(kl$Jf4S  ЋtxDž1tMY C4tP44B@Q@1ƒtI4$VF6t~4뱀~@0tF4D$ (kD$$w(4D$ D$D$0$749\9u ~08f9n9\NFD$$& tt 99D$$l9gwF4D$(kD$$uU$|$D$(kuD$4$t yA0t $LP(k<$txt$LP(kǁt$LP(kLJǃǃt~ t$LP(kLJ t$LP(kǁ  ǃ ǃBxt$LP(kAxsxx󥋽<$LJt$LP(kǃt$LP(kǃ t$LP(kǃ t$LP(kǃt$LP(kǃD$$3D$$3D$$3D$$3ǃǃǃǃt$LP(kǃ$LP(k K D$ A4D$P(kD$$Qr=džHqD$t$$І(k>$(k膂_|$$(k+D$$D$G $9$(kl<t :t$T$ D$$D$tHt<u%D$(kD$$ lC8닍fD$$%94D$4$u44R=oN 2=,N =XNǃ1niV=jt&=>$p} !kngoC0v]u}]Ð=Q'=('H t&=' U=' =' ='u10늃6N f@ ;:9>11+= = ^= =f =1$V:\)e    1Hf=' x='t&=' ?='61/=o' =c'v=\'m  =V'18=4'k=,' v{=)'; =*']u}];=}'D=v' E=q'3 =t'KK6t\D$D$$Bk{C`9P9HPPD$$^ksD$D$$jCPPCPt{CPt`t $iCP`PtP |@D$1$jM1F=Z= =G =611='='T C=' ='/,f-  *d +y>1 1\=u=N =ND =N1$==  =@ =1[ wxT7 P Q1\='  =' ='R1Kb\`">11=h'E~=f'?=g'D [611===|1u=N=N=NF1?=I' =5'=7'1$ w?qr1='='='GDEr>11d="' = '(=!'51='='='1<\='wy=W=1T3Z 052x11j=up=uG=u;V1+= ==1Kǃ11]u}]ֽ1<1ǃHǃi1O1@1&=?ǃ111d蘻ǃH1X}uEt]]E ]hǃ11hx1^10O1<@1011"11 1Pgǃl1111 11,dǃH1ǃg1@X18I11X311V1 >v;t|;pv9dt1pi1(Cg)k1@({1lV1T611>1/1؆ Tt'Pt$LP(kǃPǃT蒸ƋP&t1ht :(kDЍ1Ltp1,Z11D151&111 611H1311 i111L14m611W1(H1$,fx0t&V1111d-M.1 XǃH1ǃi16g tp!ƒP  ǃHd:14+6ǃH1ǃ ǃ11@2'ǃP10ǃ1x>11(buOǃL1K18<1-1ǃH1 Ȅ t1 t쉓L1Ȅ8t1 Qt쉓P11y0kǃl1ZǃH1I=t!=/11P!1$)| ='t='O1='t='#6jD$̈(k4$_`1$1/=N't2=O'1M4t51111=&'t=''1x=i't=m'k1(d 8]uE ]}]Z=t!= 611`>11\=t=11 w(k1yt=14>11D='t='l}]u]E ]?='t='6Lt'Ht$LP(kǃHǃL襮ƋH='t=''=ut#=uV1V1x!t"b1D[1@L=t!=2>11$1$# JtK>11611 =Nt=N11cte1611<p=~Nt=NV1O1@D$Ј(k4$ `1$򍃬趬ǃ1ǃ1D$(k+$K1ҍfpt E‰$PP(k3pt tD$t$<$1 C&DD$Ո(k4$$`4$DP(kmD$ D$$ۈ(k蔿D$D$F D$ D$`$D$4$1LP(kǃ1ǃ1ǃP4(kǃ1ǃ4(kdǃ`?ǃ?X$ǃX$$CPfD$1$1蝪ǃd1聪ǃdt$ D$`$D$D$ D$D$$`Kv'UE UT$P$T$A ɃÍ&UM Uu )@t 9vuD$D$ $ 1 UWVS,} ]tEx1t  19‰։D$$StMuh$D$6tt LJx$D$]E ,[^_]t$ 19‰U]vLJt댍t&11]t&U(EtRvtB1ÃuD$D$D$ T$T$ $ ÉD$D$T$ T$T$ $聯D$느t&U(E]ut;p4H@u0t$\$L$ D$D$ (k$K]u]Ëΐ&UUS4@ t[]1[]ÍvUESt4R$t[]t&1[]Ít&'UEU t#4It4]At&1]ÍUEU t#4It4]At&1]ÍU(]] uu}t)t4@tr1]u}]Ð$D$耸4$Xu٥ $4$-u4@t\$4$Ѕt두džsvUWVSL]3D$4$4@@E ǃtFLt$LP(kǃLD$$M(k-wLFFH100EE[F(k{4|$L$T$ D$D$`(k4$HED$ED$ EԉD$C8$D$EC]\$D$(k4$t#\$D$(k$u߃,[^_]ÍvUWVS]E EED$ D$(k$D$(kUEE;UH$D$Ό(kD$j;D$$@P(kEtt :/EE4$>h)kUD$(k$D$6EEEEԅt $h)k}UtEEt E$h)k$D$D$D$D$D$D$ D$wǃČ[^_]þZEZ"UD$(kT$U$%:WD$H$ތ(kD$EU@B$DP(kUBD$?$!P$D$?UUtFUrUB8t puEpUt)UD$ D$t$$KUBtqEp 148W׋UD$ D$D$$M[KUB M uZEZD$(k<$pEPiUB tjPuXEp1ɿu$v48W׋UD$ D$D$$MrJUBMuD$(k<$蛯+D$(k<$胯1҅D$(k<$iUEpt8UD$ D$t$$I4$LP(kExr8@@UuD$ۍ(kD$(k$}6=h)kt$D$$EEEt$D$$׋T$h)kD$EUĉ$҅E5ME&$h)kUD$8(k$D$0EUuD$(kD$(k$5=h)kt$D$$׋D$$h)kEE 11.&UEԉD$D$B D$BD$ BD$BD$E$h)kE$'h)kUD$Z(k$D$0E&}Et$ED$$׋t'D$ET$Uĉ$҉Eu11ߋEԉD$E$h)kE11EEh)kED$E$D$ D$j(kD$$E/ED$ D$$D$/D$ D$o(kD$$/E$J1҃ƋE׍UT$h)kD$E$҅ELfEh)kD$ED$E$҅EEEEvUT$ @D$$D$/U1ҋEUD$ D$o(kD$$.u}UEUUJD$ D$q(kD$$.ED$ D$$D$|.D$ D$s(kD$$\.E$EPUu}Uv(k|UUT$U܉T$ T$U@$D$1ED$ ED$$D$-E܉$LP(kE1EU&Eh)k$D$ D$o(kD$$r-Ut$|$$yEh)k$ҋED$ED$E$h)kEEh)k$ҋEtD$$h)kED$E$h)kEE1&ƋE$h)kEh)k$ҋEh)k$ҋED$$h)kUD$ D$(k$D$+EEE1uD$(k<$訨?E@UH]Éu։}M=$=Ǹtz\$D$ D$<$<D$D$s<$ED$ M<EUԋ@;]ԉ4$Cډ\$D$^<$<M1]u}]Ít&'UE $t<$t<E U8E ]u}ttt}v]u}]Ít&U ?M<`(k#(kt$ L$|$4$D$D$x(kD$CCt$$D$D$D$ 'U1}$D$T$ UD$T$']u}]þ2J$(k(k\(kR(kHg(k>t(k4(k*(k a(kǎ(k E}V(kt'}+(kt}7(kt}G(kj(kEȋU3<$(k(k(k(k(k(kӎ(kvU3`(k렃`(kNfU8 $M܉]u}ljUiU ‰ƉU$UPP(kU؋M܉øtoL$ T$D$(k$_AU D3$T$UT$EUDUx\$$腢$LP(kxUt41]u}]Ë$xUщ'U8]]uƉ}׉M$wM$D$]u}] UWVS˃\EEUt@4$PP(kEE\$ D$(kD$ D$Eȉ$.@] EM}؅ɉE~)t$<$D$(kD$ ?;]u׋ED$(kD$ EȉD$E$+EMȋU$EE$LP(k\[^_]Í&Uuu]] }}7IƉD$ED$[PC $.:x]u}]Ðt&D$C $:|gEQō&t1D$D$_(k$U%E7]u}]i)kD$ (kD$Ǎu&7pT$$7D$I(kD$뗍 ~kUWVSLDE10 wR uBXCd1NB4Bp~ vL[^_]ÍvÃL[^_]B<BxEB<BxEB<B x1EB E0< wB qE]u$)UMD$(k $D$UB$:)@~^ M#9 UB$)UBBf$(UD$p(k$D$ ƉD$KEĉt$ D$b(kD$ $/EĀ8$U(kEF@$(MD$(k $D$F@$(D$3(kD$ D$ Eĉ$v/EĹ6(kU$EFPt#$^(PIFPt#$4(PI!FPt#$ (PIFPt#$'PIAFP t#$'PIFP$t#$'PIcFP(t#$b'PIF@,$4'PIEĉD$F@,U$ 'UE(kET$UD$E$](kK[FP t#$&PI FPt#$&PIFPt#$j&PI)FPt#$@&PIF@$&PIEĉD$F@U$%Ub(kET$UD$E$q(k)9t&FPt#$%PIFP t#$t%PIIFPt#$J%PIF@$%PIEĉD$F@U$$Uy(kET$UD$E$q(k3CUD$D$(k$fEĉ@-.MT$$D$*tEEĉD$F@U$I$Uy(kET$UD$E$h(kEĉD$F@ U$$Uy(kET$UD$E$f(kBqEĉD$F@U$#Uy(kET$UD$E$O(kEĉD$F@U$w#UE(kET$UD$E$O(kyEĉD$F@U$1#UE(kET$UD$E$M(kp EĉD$F@U$"UE(kET$UD$E$K(k*EĉD$F@U$"UE(kET$UD$E$I(k)EĉD$F@U$_"Ub(kET$UD$E$h(kEĉD$F@U$"Ub(kET$UD$E$f(kXEĉD$F@U$!Ub(kET$UD$E$Q(k!EĉD$F@ U$!Ub(kET$UD$E$O(kEĉD$F@(U$G!UE(kET$UD$E$X(kEĉD$F@$U$!UE(kET$UD$E$S(k@WEĉD$F@ U$ UE(kET$UD$E$Q(kt&E]u$g }}ąU3MD$8(k $D$eUB$UBt$D$H(k$4LD$V(k$ƀ%D$ D$D$$4$肀UB<$D$EtD$(k$D$ UB$ <$SUBUD$(k$bD$$(k$m EM$ME9UD$E$ʃMpE$UE`(k$E]]ĉD$D$ $y]D$Eĉ$$$EuU EԉT$$bNjEԅZ$~$9tFU3D$e(k$9 E=`(ktet$+v1΋UftD$X(k$D$ USB$)UBM$T$U3MD$(k $D$ EԉD$q EBEtD$(k$D$H USB$$4$}_D$Ԕ(k$D$<$RUB $ƉTXE34$t$ D$(k$D$ EԋUD$(kD$$_EPE1>$@D$D$\(k$DUEt'$|$D$Eԉ$|E8M3D$(k $ED$c(k1$ 4$1t$ D$$(k$D$ 'UVS @)kutpt4`(kD$D‰$dg&苘${$$UE\$D$'$LP(ktƆD$@$tD$$uD$(k4$  @)k 1[^]ÍvUWVS|0RLP {$SBD$D$4$߳KQ8C $x'D$C $8fC=m= bT$$D$`(kDž#eT$ D$D$ĝ(k<$-|[^_]ËEDEljD$ L$D$$3xMDžwt&C C$>$>D$ɝ(k<$D$R SɍB>5DžCuC $uaDž<(k&CfD$ D$(k<$D$$$D$q(kD$D$ `(kDž<!D$D$4$(y$D$L(k4$4Džt&Dž<$KP@\"t&{DžNjSt$h<$hC2D$ D$D$!$Et7PTD$ D$ %- D‰D$C$p҉tS8t4T$$TD$%k $FoD$(k<$\$&Dž:&]Džtg!}CDži)kD$L(k4$D$Dž#uDžDž0C $gD$ǍD$$m;u4;)D$(k4$ D$$<D$|$$=X1ɉpCMCP%kDК%kD$d(k$DžDlDžD$$^D$(k<$D$,DžtɉtCK83*4tD$C$T$D$C$!Xh(kD$@(k<$DхDT$ D$'DžMD$%kD$C$5D$(k<$*+D$B(kDž $8rgD$$$qD$D$ D$D$$}0D$$(D$(k<$D$$Fwt&D$D$D$ C$sDD$̖(k$])D$T$ $xt2D$(k<$CT$ $Nu1ҋn]D$(k<$D$"(k$Dž;DD$D$ :(kD$D$ $DžD$L(k<$R'D$ț(k $(kD$(k<$DхDT$ D$bMNjC$|$$<t(D$$T$ D$(k $D$DžRDZ*J+V$h$Tt<$z $6D$$\$N $$ D$(k<$oD$D$D$ D$D$:(kD$ 3D$$D$(k<$$f $S D$$CD$(k<$$< $ D$('k$( mMҋED$L$$ D$̙(k<$(kEL$D$ <$|D$ (k4$D$(k$D$.(k<$C$ D$ $D (kD$K(k<$D‰D$h1D$@%kXD$C$ t$T$S $T$ЅC t$k C$H C $} CT$$D$D$D$$1ED$C $  D$$z D$(k$D$HDž# D$H(k<$\$D$(k<$ D T$ D$T$D$t D$ $< D$*(k<$$TD$t(k<$j?D$(k $/|$C $ t8C1D$(k<$ Dž D$$D$1(k$D$Dž#D$ $8 D$Ș(k<$\$D$Ț(k<$pED$h(k<$T$Q&$1D$(k<$'-D$$%D$(k<$L$D$ $4 $1҉k\$$D$D$$D$ N (\$$ $D$ $Q9|$$cD$('k$T$$D$ D$D$7D$ C $9 D$(k$SD$\(k$X&D$p(ktD$D(kgD$(k<$L$PD$(k<$ D$D(k<$$hvU1҅t xÍ&Uehk$gÍ'U(ED$ED$\$҉Ðt&U(}} ]]u<$Dt $D$ǃD4$tD]1u}]É4$t$D$$t$ |$$D$D(k]Bu}]É|$$D$'(kf]5u}]Ít&U]]u1Dt6D$$%D$~(D$p(k$D$]u]Ív6$D$(kD$]u]ÍUWVStJ1$t,$<$D$ku։<$k1[^_]Ã[^_]1ꍴ&'USE @P]C t%$C $C $dC Ct$C[]ÐUWVS]u vP\8d\B ~L4v`D$ 'D$D$$)s`pD$xt$PB X$XD$B ${vXi)kXt$$|$ D$ː(kD$1ۉ$\B $\B Ĭ[^_]Ít&t{1ud1D$(k$tfi)kdD$L(k$D$KwdD$(k$ t&d1D$˞(k$4v@ $\B E $D$ED$0E\$$)t[]ÐUVSD$$O@)k@@)klibcD@)kurl/H@)k7.28fL@)k.1N@)kf+tBN@)k )ÍO@)kQ\$4$D$ (kD$ @@)k[^]Ðt&N@)kƍt&UD$P$ A)k*P(k A)kP(kP(kÐUS$$^ƅt5D$\$$(g)k t$DP(k]1]Í&UE]뗐UWVS,}] wu $]p4$PP(ktMuEu1DE܉B;]uމ7,[^_]ÃEE9Ev eEU؉4$D$HP(kU؅t&ƍ>T$ D$(kD$$[딉4$1LP(k,[^_]1UE $D$ED$Í&'UWVS밉T$$ (k(E؉t$D$(k$^t?t E8Ct>rut`T$<$U(ƅ됍T$U$1(ӃDXtIukubDžƅ&D$?T$<$'ƅT$$(k't/ƅT$UD$?$Q'ƅT$$(k]'t<ƅ&$&uBL[^_]ÉT$$ (k'DE؉0$LP(kE$LP(k$(k tZD$ "(kD$)(k$+(kD$EtDžDž6$LP(kDž"US]ݓǃ܆ݓǃݓǃݓݓݓݛt $LP(kǃ1ǃǃǃƃ ƃ@ǃ<ǃp[]Í&U+SUt]M tl~P0@uD]t=} @#} "@} @u $d1[]Át2+[]Í&]tE - (w$8(kt&EtNjM (w$ܬ(kt&EtM 0w$(kt&t1q@1b1S 1D15l1&11H4(kDщ1݂1݂1݂1݂1݂1݂1݂1 ߪx@rߪpߪ1Mߪ1>ߪ1/ߪ1 p1<11111D$$_1111w1h1YT1J1;T1,11܆1$G]EK1tRU1V1S&?Dރt utuf[^]Ã1Ít& tXUV1S?Dވ t& ut$%@2@0 u[^]+Í'UXEuu ]}t$D$$L$ =)=N9 (kM݉|$ $(kDt$D$C(kD$ M‹)ЉMЉT$$UԉL$4$wL$t$M$UԋM9fU1:]u}]Ë t&E$D$ (k藫]u}]Ðt&$D$(kpE]*u}]Ðt& t U1]u}]ǃ/ UE]uǀdt 1]u]ÃHt닃htED$ D$D$$ЅtD$D$H(k$zA롍vtVD$$T$D$h(k$ƉD$]t$D$(k$AAvP4(ktD$(k$AD$D$<$뽐USU ]tDt@t+9~ v[]D$Ԯ(k$Z1ǃ9|D$(k$81ǃ뺍v'UWVSu>džE_*oE}5EuU ؉EEEE@WDEUEEE!Ѓt GHbEM܉L$D$ D$@4$D$QS8KMȃM 41@<t1҃xXED$D$@4$UMEUME1EEtEЉ 4@>]1҉Éuu 90< u  uÃ;E)t$E܉D$ G\D$$D$E܍M܉L$ D$G\4$D$qD!V$|T$D$t(kU$U@V$0uUCT$D$(k$U)dž&S8K$&t2ƃ[^]Í&$D$(kۓ[^]fǃ$$Vu,u2 !$!([^]ÐD$$DpfD$$4pfU1]É'UWVSL]}E׉D$ E؉D$E D$ɳ(k$E D$ $Ut5E !$PP(k[U cU $LP(ku }ǃLtHt $LP(kU ǃLHT$D$ܳ(k$L܆=.=/2=-$D$ 5$L1[^_]ÍvXt ;TNTǃTt'Pt$LP(kǃPǃTH$DP(kPt ǃTWE$LP(kt&L[^_]ÍvH$DP(kEtD$ٳ(k$PE DU0Uĉ/mUD$?$rt E 0?t UD$/$t E 0UD$/$+} EPDU1Uĉ.@Mąt7t3}Ƌ} D$/<$uUċ}ƋE$EDM$PP(kMEL$4$MD$MEtCtÍKluEA)k1ݐt&˹uUS]u []Í&U tMtUtދMt׋A)k0uˋE$ uU LP(kPP(kUDP(kUHP(kU@P(k됍'A)kt A)ktUA)ku%pkA)ku A)ki)kv ԉ'U( A)ku$TuE$uE1Ð&U+UtED$E $D$xÍUS]t%Ct+@t$ttj][]+[]f@t&Ctt]$ftC믍vuC~u멐D$$Lttԋ$JC늍vUEt]]Í&'UE UBt]ǂp]fU]]}{uAuJ1tftC(C,]}]Ív{CtffUED$E D$E$Q UVSuD$$@P(k$PP(kǃt$$ǃtǃ`t1T$ `T$@4$D$&`Xt$XtnHt$DP(kHtQǃLPt$DP(kPt*ǃT@D$@$gtt PX$ǃXt$LP(kǃHt$LP(kǃHPt$LP(kǃP$ $1LP(k[^]É$ǃt^t&$8ǃ|ǍUWVS]t$LP(kǃǃt$LP(kǃ($p 1tft4$hG1tft$4ǃǃ[^_]Ð)ƃ(Rt&f=iƃhkt&fVUWVS,]U Ѓ؃σ ȃ 1 Ш҉UtsǃUU܉UU@@F|$ T$UT$$:zut 9u&U܉M؉$LP(kM؃,[^_]})uېM؉t$$HP(kM؅t'U䉃t$$T$MM뜋$LP(kǃy U+S4]tWPtSED$$)t_UUT$UD$ET$ U $T$BuuUM4[]É$D$(kPx4[]Ðt&D$"(k$0xÉ'U+S4]EtfPtbED$$)UUT$UD$ET$ U $T$sUt?u,u(Qf4[]É$D$(kw4[]ËM4[]Ít&47[]Ðt&D$"(k$Pw멐UWVSÍllj1tft(kމ<*tLE_}vt(   E7E.1} $ % t&  t&uFCDFF;uԋMԋv AuAC<A@AAAA]ԃC   wt& juԋFC<F@FF0]ԃC-& 0 Jt&uԃF X WUԋMԋBBCDST$ |$D$$UYU? C? g&PvJPЀ vBPv:C^MDD$D$ $CC SDST$ |$D$$U؉MLXU؋Mԅu<[^_]Ð MytMT$$U؉L$-YU؅uM)C )ЅC ]CQ$D$H(kW M D PD\ǃC fCC@fC uYC ǃvMytMT$$U؉L$WUǃ$PP(kCXt&C 4D$ D$$D$V Evs$UWVS]u uoD$4$tu1[^_]Í&E{8Cu(E8tD$4${tE[^_]ËE띐UWVS,UNƉD$ ED$$D$s<$9u%t'u,,[^_]Ðt&fڍ&UVSÃ0D$EE$g)kED$ED$ D$D$$8i)ku#]H' te[^]i)k֍vU(]Éu։}ft"ftl]1u}]Ít&CD$ .T$D$$wtC$Hi)k]u}]ÍCD$ .T$D$$Awul&U8Muu]}t1~totrt 1t>M tjM |$ t$QT$$Q)ÉD‹]u}]Ë11u뜋9OʲEEUE 냍UMVS XXX XXXXX X$X(fP,@@XXX XXXXX X$X(fP,<p[^]ÍUH]]u}3 E T$Dž|$$0i)k t>i)k$D$Zl|$D$(k4$D$ P]u}]Ðt&hD$E DžT$$4i)k uzbu1Dg)k$D$k|$D$4(k4$D$ P{htRf$]u}]i)k$D$wk|$4$D$ (kD$ O]u}]fDg)k$D$VtS~ttP SPwgS @KT$ $D$td\$D$$Љ‹EtVp0t;te[^_]ÍC fS(e[^_]Ðt&CD$CD$$di)k‹E 땍t&'UWVS @,MDžH4E LD$ XD$@T$$e[^_]ÉL$$Ui)kMԉ$D$ExYD$D$ D$Ǻ(kD$Eԉ$=Uȍe[^_]ËE̍U$ND} MuED$Uȉ$=Uȉ$UẺ$D$UUԉ$i)kb$(D$ET$ U$T$舝019UԉL$D$(k$AE̍U1E؉$D$BXUD$"(k$D$[AUЉ$T$1n&щ‹EЉ0s<$D$UU U$PP(ktU@ @PÍ'UVS]u $ PP(ktQUS t*tQVpPVtVBFC [^]É@BCٍt&1[^]Í&@PB밉C먍U]] uutQN tJ9tUCSPCt_SPD$E$VCC$LP(kn ]u]ËCtC@묐t&CFF UVS]u u*t$C$D$)C u]LP(k[^][^]Ít&'UE]@ Ðt&U U ]M}]u}q 1tL9tpBrpBrpq q C u+B@SC ]u}]ËGzBGt@PWҍvBt7B@q 땋]1u}]ËBq AxS뾍AaU]] uuCt$LP(kCt $V CLP(k]u]]t&'UWVS,EutU t}u,[^_]f]tUFEFV U FV$PP(kM 1ۅ,1[^_]f;] t$&k<)uލSۉUt21D$$;}u׉$LP(kF(fF U8]] }}utWutPtLMtE$PP(kt2E|$\$4$D$ ED$t4$LP(k&1]u}] UWVS,]uU C;t$$D$S8Eu ?t8M t$ L$HL$@$St؋U\$|$$k$ PP(ktt4$EPP(kUtVE $t$M܉D$"UM܋ErJMT$A $UD$xUt*CE,[^_]É$LP(kEE,[^_]ËBU$LP(kU$LP(kE붍vUWVS,]}U C3|$$D$S0Et_&tIU t$ T$HL$@$St؋U\$|$$E1k,[^_]Í&,[^_]ÍvUWVS]C3D$ED$E $S8u 5t.E7D$ E D$FD$F$StՋ[^_]Ã1[^_]ÐUVS1ۃuF~"t$$;9^ދ$LP(kFF[^]Ít&UWVS,utlF~eEfU8Eu=ۉt7U _$UD$҅tU|$߉t$$nuɃEU9V,[^_]ÍUS]t$LP(k][][]Ðt&UUS] 9s19u1u[]Í&'U1SU ;Ut[]ËM] 8 uE]T$$\$n͐UEtLP(k]]ÍUEU]19 ÍUE}]ÍU]Ít&'UE ELP(k] UWVSӃ,$EPP(kǸtt1CGE$3t>Eu3t&Cޅt&ËWD$T$ PT$$~ыE|$t$$>1t,[^_]É<$LP(k,[^_]Ð&U@hD]Ít&9 Ut t]]ݍ'UWVS,UM܋MHhU؋Mu#\$]D$$6]t%St$|$ UPT$$~Mtq] HRM؉Q]D$D$$EM܋]PD$ D$HL$T$M܉,1[^_]Ðt&]1ǃHǃL,[^_] U8]Éu}ƋUм(kD$̼(kT$$覎;p @|U;P}6Ut$T$ P@ T$$]uEЉ}]]u}]ÍH|uDU(]u}p tX{ wX v1]u}]$(kv1D$T$@ $͍t&H t4X(1tD$T$ $렍&D$T$@ $뀍&D$T$@ $y]t&H 0E5D$T$@ $UWV1SÃ|UċEč}ԉEEEEE]EN ЅE=]D$EȍEȉD$C\UM$UM1UƒMDЅ 9St:MALt-KL$MIPT$L$ MȉL$MċIU $ЋUSL]EE1ҋH8]Ӎ&MąT$Ut";U1t&;9uUED$D$B\$ tvQ MR ҉UUE҉Utz vUċME;JMɉMt]y vWMċ;QUUă9Z8!EċU|$$T$$hUĉr8|[^_]EUtMQLt+@MD$APMD$D$ EȉD$A$ҋEMЋP\ED$L$$UEUSED$D$$,7EčM̋@EE@\D$L$UE]Eȉ$EUD$$@P(kUME̋MC Ẻ\$ D$D$ $UgU`$LP(kU tG9UUuFI BMtB 9MMuARP]UR MUEUMU8]Éu}@ptcCXtGUCX6Ux1Tԅt9Vt19Tt9u?w T>}As2;1Tԅt9St!19Tt9u?w T;ft9UMUăUk}E?9lj}HE}ĉ8<1[^_]UWVSLUt M9 tL[^_]ËyMu9ω}tK]fEĉ1ȺsystuՋMċ} 9Mu4$1PP(kM}IE9Mtq]ԍE61Ⱥs}č<fB:ys}č<fB:tuM} 9MuEt-E Mċ}f HfJ9uu1ۅu"Eĉ$LP(kEt)U1L[^_]ËEt$D$Eĉ$X1t&'UWVS,]t; t,[^_]ËSd1zR&9r~C<t苈4A@tD$$艓Cd8Sd9rslu<>4$LP(kt+FǀFtՉ$詻ˍ&C\$uCdC\$cCdD$CH${CCHE9u2[vǂtD$W$蓦<$LP(k;ut+W7zuȉ$谐WWBW먋CT$CT$LP(k,1[^_]ÍvU(]]uu }tV; uNCH$>t?CH:T$D$$CH$$]u}]Ë]1u}]ÍUUt: t ]Í&} 'tXw} t?} u%EBh1]Á} !Nt} $NtB} 't/]ËEBL1]ÍvM1B`1]ËEBP1]ËEBt1]ËEBp1]ÐUUt: tÍt&BXtBXU 1ËE 1Í'UWVS,]} st|Hu Lt`FXhD$PD$FX$܃t*vD$G<$D$yG uǃHǃL,[^_]ÍUMb)iM)i}?B}~@BM}䋃HHuJLu@PEU䉛dHL|$ NX$T$L$FX,[^_]ËHLD$ET$ U$T$sh~)U,[^_]ÉD$D$(k$u&PFXD$|$FX$mBD$D$D(k$1&)UWVS,R M܋H ʋ|Uu1,[^_]ËEM19Mv݅u ׅtDH$\$D$L$ D$$覓E䋗9EwM܉ $9mLJxD$$$,[^_]ËEJU}}]uEwUMEEt |t؋u]}]Ë|gW Gv2G Gtz4$NJG G11ۃ-uGUGwG BHWT$P$T$kۃMGA3$h(kG D$4$1G1pG 1ۅti4$D$G 4$D$G }G G D$D$ۉ$GG tG G G1ҋG!dž|G ǀxG ǀtG 4$UD$G 4$D$G 4$D$G U5GWG/G $  G* t;; t;; @ G 1; G @D‰D$D$T$ $T$͆D$G t1ۋ 1҅0;1(ǀt G _ u ^vRtT;2uE@ $T$D$ ED$tǃxD$$_  G rED$G E$JGEEE؉D$G $=GeG 1ۋGD$4$OE؉D$ ED$G D$4$G_ H MEI 4$MEE|t L$4$MM;o G} }G t GG x1ۋ 1҅;1ǀxlGE܉D$G $G+E܅iG у GWG1EP$G ǀtGG@E܉D$G $_G]܅ G E؉D$G $W G0tdžG@GEԉD$D$G $uUԅ҉GG1+E؉D$G $>G4$+D$GD$G $1|0ۉ|$D$p(k4$D$ (Gdž|GG G to$蔍tcG WǀGɃ GfW T$D$(k4$G)ftGGJPD$ED$4$AG)\F8VuO&>t@u믃~w   9u~E)D0E렉uEEt"tE8t>t u뙃Et8)1*&Ut$T$D$Լ(kB=É$D$(k+=Ít&UWVS<E؍M$@MPP(kERELJ@D$$vS$Z>D$ 8D$^(kD$$uVM܉M1냋=@t tiuҋE1$LP(k6E$LP(kM؋$=LJ<[^_]Í@)ƋEt$ D$MԉD$E؉$xMԅdƋE$LP(k$W=LJ뛉$f?=LJ<[^_]ËE$LP(k$=;$1=LJFU8]] uE}uEuu8Mσ1umucEǃ0&kǃP&kD$8D$^(k$uDǃC\ډE]u}]QftMu]}]ƃ7:f6UWVS<] Eԋgt6C\E1tEf<[^_]ÍED$<$HP(kpS\1M+ET$L$$p ~8$LP(kp&}Ժ81ǃ0&kd(kǃP&kD$ 8D$^(k)ШuHUD$/$ǃC\ډEEAED$$kǃ} C\lM $PP(kS\1$T$L$oǃ2ff名t&8MGNjEԉ$Z9ǃ<[^_]ÍMx*Mt $LP(kM䋃ǃ))US\<<$LP(kUԉ$8ǃ(xUMctES\ǃ‰U)‰Љfpƃ7PEԿ$ 8ǃ'USEt$7ǃ[]ÐUD$($@P(ktÍUS]St []Ít&} v vE $l(kEC1̍EC 1뼍EC1묍M!uCt$!1CivM fVSkD$ D$D$$aC<1uC C D$T$@P(kC$Ct1fC$=1CKcC^1cC$LP(k1CAt&'UVS ]Ct SD$D$$T$ ЋCCt$CCt$qCt+s t1kTЉ$2C9s w$LP(kC tSD$$T$Љ$LP(k1 [^]ËS tKED$$L$ҋE [^]Í'U(uu]M Vt10t$ZtREL$4$T$ UT$ӋE]u]Í&U(uu]M Vt*0tZ tREL$4$T$ӋE]u]ÐUSÃt $LP(kCt $LP(kCCt $LP(kCCt $LP(kCCt $LP(kCCt $LP(kCC C C[]Ít&UWVS1ۃ4$D$(kD$D$ uՃ[^_]Í'UWVSLEM ]5Hh)kąE‰ut&t $օuD$\$$(kei1{mS5Hh)kDžDžӄoÉ$օ==Ѝt9.=u=G<"DžDž2< $< ʃDžtEҍJt><"~<,<\fuƋu\DžuD$(k$?g$DP(kuE&É$օu担tJ2"L[^_]ËDž1t&1҃D$(k$fftVD$(k$LfGBB .,udX_D$(k$et:$DP(kBL[^_]fKD$(k$etN$DP(kBGDž|D$(k$:e$DP(kCD$D$(k$U-D$D$(k$D$(k<$duD$(k<$dD랋D$½(k$`d[$DP(kBfD$̽(k$"dB  $LP(ku$(k$(kDP(kBL[^_]ËD$ս(k$ctB pƅCt&'UWVSU EDžlDžpҋ8H` d$\`t$LP(k`dٽ(kdDȅDd\A C QCXt$ dC$(kL$D$ uD$4$<$LP(k$!PP(k‰{ \AQED$?$%a6+E$UM$(kT$ L$D$< …"CtD$(k$XaXT$4$X X$LP(kUC=ML$D$CD$C D$ |$$(kD$X<$LP(kXD$4$X$LP(kUhSKCs ;\M D$ ڽ(kT$ \t$ɹٽ(kDML$$MT$|$D$L$d$(kL$`D$(kC$M``1Ct7t$D$$(k`$LP(k`1Ct3t$D$$(kltf`$LP(k`14$ _4$D$HP(kt/$^f @`1<$LP(k&[^_]ÍT`ąd \KCC tKD$(kD$!ЍUlj$D$ X}X$7^XpL$lL$ <$T$D$MBlC.UE$(kT$D$A 1[^_]ÃC CD$ |$$(kD$D$4$XX$LP(k ED$ |$$(kD$} ٽ(kڽ(ks$(kDML$Mt$ T$D$L$dL$3`ƉWt&US]ą[[]KUxuu ]]$f4$\$趿t$$D$NE\$$G]u]Í'U$]uuPP(ktF $PP(kCt3$؋u]]É$1LP(kt&'UEML$M L$@$R1Ív'US]ST$U $PC$LP(k$LP(k1[]ÐiA)kmNAU]90A)kÍt&U$Zi}-!XA)kÐUW1VS*L'm3O'M'N'<(kg9'V('r'''>(k4$WD$$D$WEƀD$ $Vt )ڃ~D$ $Vt )څ~9EtE$xg)ke[^_]Ál'$=*m'u'uq(kD?'2B'$@'A'u23(km(kD$D$$VEƀD$D$\$D$ t$D$$,g)kt$t$ D$(kD$$bv(kkvI'<FG' H'd(k4V'DT'(U'0(k<'):'t;'(k5' 4'};3'(kf7'C(k((k\(kO(k{C(kq(kg|(k](kS(kI(k>(k4(k*(k (k(k (kI(k(k(k(k)(k(k.(kt&*t| *(kX(k=(kD'j(ksV(k(kOaW'tk's(kC(k9't&'Jӿ(kƿ(kJ'tK'" (k(kQ'[(kQ(kl(kO='t>'(k(kU8E ]]u}M;WtD$D$<$1UD$ T$<$D$,FtVGtD$<$UU䉓ǃ]u}]11ۍt&1΍&EfU$SU듉'U]]ut C8ǃE $D$諘tD$$UK]u]É'U]TP(kt UD$D$$di)k t)D$$TP(kTP(k1ɅTP(k1Ít&'UE<t]]dUXu}׉]PET$PT$PT$U؉$D$@(kD$D$ UЉM+UЋMԉ֋!Á tÀD؍FDۃ)9s-t)t$<$T$O]u}]Í&$1xg)k]u}] UWVS|Et't>$?'xg)kEEe[^_]ËMUE EEe[^_]1D r11tM M+MM Tu1ɺ11&$t'tttt9~ƒuكJt9ωоME1ҍ 7Ӊ}ljEM9]~9t`t9~܅t#:uu}}D<$D$L(kD$D$ ǃu}t +]9]ED$E$NEe[^_]fؿt&}sME ڋ})ك. tB$%Mz:t&:R$xg)kEUWVSMEEEDuEEEEEEEu[t&I 4h)k<$хt<$=8h)kׅ90 } Dg)kыxg)k$UEҍEăD$ D$4$L=Dg)k׋MU9t $҃$Mĉ)1}~} I}EE΅Ht m}} Ѓ}} }1}e[^_]1<$=8h)kׅE1Dr]ȉ\$D$`(k4$Jى]!%tDQE)ڃ}U}^}uO(k (kt=|$$Jtk<}uu}e[^_]Ã}u0}u*}UEEo뭐t&1E-x*9u!~+‰։-t غQ)k؍k&UWVSÃ, 1ƍC$$-t$D$C$vgOt&]Mb)ιgfff){$K >C(C CL$D$C()D$ D$(kD$C,$ɾ$,,1[^_]Í&Mb{$)ιgfff>C()K ~tC>2A¹2C 25C'D$(kC$*,[^_]ùCC ` UD$J(k]ÉuD$`(k@$蓽t ]u]É؋u]]6U8]Ãu}@0/kT$1D$(k4$@]u}]ÐNűCCD$ C0D$(k4$%D$ռC 9C1C]u}]ËPP@C0PfJPB8D$ D$D$D$PD$C$\i)k1]u}]f8D$ D$D$@D$PD$C$\i)kF@1VD4$D$T$+fC0PCP@C0PfJPBDf{0v 9@+@T$D$C$k !8D$ D$D$@D$PD$C$\i)k(@N@^DN@^DL$\$4$*LP@ S09 fu =D$L$ D$d(k4$~C;C C~UC07D$(k4$D$s.i)k7D$C$D$(k4$D$@81D$ D$D$@D$PD$C$\i)ki)kf7D$C$D$(k4$D$´}C,$'fC0&UD$(k]ÉuD$`(k@$St ]u]É؋u]]U(uu]}4$vuD$X$@P(kÉLP1džs0HCCǃDF<@fC8u2F<@D$C8D$C$i)k dž$'E ]1u}]ÍWG.]u}]ÍGD$$@P(kL ]u}]i)k4$D$wD$(kD$$豲]u}]ÍGD$$@P(kP됍t&'USE$3t *[]ËC[]UVS]3CtD$(k$%tB@$%$EK(9S,S9cU )D$ D$D$C$ t_IuVS t5Ft&C,$5C(+EU ~Hu1U ;uI1]u}]fE C<$D$j(k躦]u}]D$D$D$D$D$D$ D$4$X"rvi)k4$D$D$(k<$D$:1C =U]G&UWVSlM] M $]=gM̋ɉM]1ҋEMă9E]̋3p]̍~]EUFPVTFXV\Eԃ8WEЅLUiB  t]ȋ9UԋRۉU]ȉD$ D$D$$RG@G8WDWEԋP EЋEԃ8MD$D$D$D$D$D$ D$ $]]ЅuMċAl[^_]OEЃl[^_]Ít& k]ȋ9T| ;MIEԋD\$ $T$D$EȉD$d E'W|9X7FV NP HVMP1Ƌ]}u]ËtEt$P@ T$$9x  |;Xv}M]u}]ÍU]u}]Ët"D$<$\$bVPU2뮍vFEUS ] Utbt^{ t'T$SC T$$¸9tD []Ã{uӋ tCACt E1Ƀ []fCtS KP HSPM1떋tD$SC T$$~SPӋCΐUWVS[^_]ÐtD$ (k$[^_]ÉtD$D$(k$ĚDžl{t&D$(k$蹕[^_]D$<(k$蕕[^_]D$!(k$q[^_]ËpD$$Np|$ D$D$$tAt!tTD$(k8$D$(k$D$(k$ϔpD$$pL$D$ D$T$$Vu t tD$(k$^Dt tD$(k$5t;<S<+vHtD$(k$lƅƅƅUt$$ƅT$=ET$p~M|$ 5D$T$$5u ;ptD$P(k$+MUt$ $L$T$tvtZt)t#JtZtD$$UD$$(kT$t$角t$$V~tvlƅJ1DutD$$ƅR1D:t>D$D$(k $dduʾ딋tD$(k$ϑ} 0}&}1} уh򮃽hƅэyhthM$T$L$ht'M Љ|$$L$dd׍T$pD$|$ $T$~u;tstD$<(k$ǐ}t M95tD$ (k$蕐{ƅ1ƅƅUpL$D$ D$T$$u t tD$l(k$D$ tD$(k$D$ۏpL$D$ D$T$$xu t@tD$x(k$耏ftD$(k$`Ft tD$(k$7eD$L ȉD$HT$L$D$DD$@D$<D$8D$4D$0D$,D$(D$$D$ D$D$D$ D$tD$L(k$' <<pD$$ D$D$(k ЋUD$ T$t$賍D$D$(k ЋtD$$D$D$D$ D$L2pxL$|$ D$T$$r;f UEPw$(k&B]øY]fX]øW]fV]øU]fT]øS]fR]øQ]fP]øO]fN]øM]fL]øK]fJ]øI]fH]øG]fF]øE]fD]øC]fA]øZ]fUWVS]u tuTNtTVt>Ή$UU$8t$8[^_]É$1$F$o뱐&UWVS u] }u:?t&tl$M1M $E"8Eu+t uƅt$E$1:E [^_]Ðt& [^_]ÐUWVSu}] t$tu[^_]ÐUVS]t3Ct $LP(kCt $LP(ks$LP(ku΃[^]Í&UWVSu ,u1[^] US$E ]uGt=00 (kD$D$P(k$D$ D$t8$D(t$LP(kǃ($1[]Ðt&ǃ,뵍'UEE]CUS]4@@t 8t&$<,1ɅҋU  []Í8D$D$$̍&'U(]]uu };${A4ǃǃ@wǃ B'kǃ$pA'k@@tptD$$u<$=ǃ,ǃ4Z(kptu]u}]Éu }]u]]t&U8]]uU}{,R 4U܉ $M1ҋMƍ@9Cr+U܉t$ $T$'u ]܀<3 tb1҃,t]Ћu}]Ë]D$$\(kU\$uʋE *]Ћu}]Í&U D3 U($D$D$D$D$D$D$ D$*Ð&USÃ8D$D$$轷8tǃ4`(kǃ,[]fUh]]u}E,0utML$ ML$D$$Z=uDEt=,,$(k0tPrf]u}]Ð$H@]}Ɖu]ÃD$ D$$MMĉU ‰EEЋUD$(k<$D$T$ M见MąD$D$$UU9UFUT$ UH}MąUEUȋE)EЋŰU9E +ED$ED$$ U)MċUԋED$(k<$T$ D$MU UЋMD$D$PD$D$D$D$ D$$EЋUԉG(W,ǃ,\ǃ,fYBf;*t<{u t <{u<{%느t&OD$(kC${OUD$CD$(k$z7fOtw0D$@D$(k$zO@D$`(k$zID$D$<$ǃ,"pD$$蕳ǃ4`(kx00 (kD$(k$D$ D$bǃ,00 (kD$(k$D$ D$ǃ,WUD$D$D$EЉT$ $D$[EЋUԉ<$D$T$pM`Mĉ$LP(kǃǃMv'U8]]}} u$=:Vt]u}]Ð,(k8D$D$D(L$ D$D$$u3FFD$D$4$aD$D$4$)D$D$4$D$D$4$9t @ 0@(k0 (k(D$2(k$T$ DD$T$%ǃ,ptFƅ@ v|$$U(]] uu}\$4$_ۉu]u}]Ë1H tp]u}]ÐU]Éu0t&82BB1]u]ÍvD$$@P(k…҉uː&U(]]}1E utEuP(t$LP(kǃ(,t$LP(kǃ,F ]u}]ǃ뢍t&'UESt1u'4 (k(k(kǀEˉ41[]USÃP(kD$(kDЍT$$4u ǃH[]Ít&UVSà 4$&2u Hu1[^] UVSE ]u&tD$D$(k4$f4tB4$j8@$D$Dt$LP(kǃD1[^]fǃH/뫍'UEE]<7US]$80H1ɅҋU  []U(]]uu };$;5ul4ǃǃ@wǃ W'kǃ$M'k@@uF$1ǃHpt;>u]u}]Í&D$$蠬t։u }]u]]vUWVS,]{ <$[,]vD$|$$(k twU䋂HtRt}u 1,[^_]À?+t!vD$|$$7(kuЋE +,[^_]Ívv|7>?+uЋE -,1[^_]Ít?.tuD$D$(k<$N3D$D$(k<$."D$D$(k<$U䃊8< < < < v>O1+v< < < < I9uуэ "<$D$ D$(kUJMu U䃊<)΅=< >< *݋U䃊8U䃊8oD$D$(k<$MMuU߃<D$D$(k<$MMuU߃<L1ɉAD$D$(k<$M]MuNU߃< uj<$D$D$"(kU#MU䃊<D$D$)(k<$u[U߹< tɃH<$D$D$2(kUMhU䃊<@Y߹M1Ҁ?ǃHt&]u}]Ð4$+]ulj}]Í&H$\(k+tD$CD$1(k$Sh듋3+ǃH8|+EED$CD$(k$gE+EEu͍ED$ED$ D$D$$wED$D$(k4$''u ǃH E$LP(k+ EED$CD$(k $,gw+EEUU}ǎ< ut&< t< t<=<$:fHMT t t t pȍv΃+D$CD$1(k$zf+EEIED$ ED$$D$|iEwD$D$(k4$%ǃH +0D$@D$(k$eǃH +D$X(k$e+D$CD$(k$qe+{D$CD$(k$Be+EEu͍ED$ED$ D$$D$.g?+EEED$ ED$$D$gED$D$(k4$-$ ǃHt&+u}8lucD$(kC$iEEUD$ED$D$ |$$D$gCW0A(kD$K(k4$D‰D$_#ǃH  t tUT$UT$D$-(kT$ D$ $T$*iED$D$(k4$"ǃH 0tPǃ<ǃ@D$K(k4$^"ǃHEkD$(k4$)"ǃH ED$ED$D$D$ $D$D$rsD$$cKǃ4(k8A<ǃ@(kD$D$S(k4$UX!UH$(kxED1Uу $7D$DD$E$xU11эQ$7D$D$E$xEUT$$xD=D$(kD$D$ D}ǃ${zuӍUljT$ D$(k4$D$U ǃH ǃ0ǃ4D$D$D$D$D$ D$D$$:~$LP(kǃǃOD$|(k4$ǃH<t'ǃ@(k 6A@tJǃ@@ 2(kD$$T$>\Dtǃ@(ktǃ@(kjD$(kC$dmU]Éu0t&82BB1]u]ÍvD$$@P(k…҉uː&UESt1u'4(k`(k(kǀEˉ41[]USÃǀ0ǀ4(D$@(kD$$u ǃ8[] USÃ<tM8t!ptD$<$$LJ@wLJ @q'kLJ$@f'k>tq(D$D$D$ D$t$$qu-LJ8pt[uU ]u}]Íve(k $D$3D^U <$T$뮍&'U8E]1ۉu}xp @,Ev>0 w3F0 w'F0 w1ۀ~ QE䃸8t؋u]}]ÍWNv $D$D$o(kU؉M U؋M܅u EǀDvD$D$t(k $u t ]f< < < < v'N1< tx< tt< tp< Iti9uу 4$D$ D$(kU5M܅u E䃈0)υR]럍D$ D$4$x$h/U D$D$z(k4$MM܅uEރ0D$D$(k4$MM܅uEރ0O1ɉDD$D$(k4$MMM܅uMEރ0ui4$D$D$(kUM܅E䃈0D$D$(k4$u[E޹0 tɃJ4$D$D$(kUM܅mE䃈0@^޹R&'UX}lj]uEE)0tYLJ4 (kt$D$(k$#UtẺ$LP(kE̋]u}]è@ hED$Eྀ(kD$ LJ4D$D$$XEuU҉UB4$E=,UЍt$D$(k$T$ %Uԉ8ǀ8]1u}]ÐLJ4 (k&8t&D$(k$~ZCt&E D$Eྪ(kD$ D$LJ4@D$$eE ED$ Ez(kD$LJ4D$$JXE&'U8]]uE uP1tF ]u]ǃ㐍ED$D$ D$(kD$D$gPu}tM$(kDP(kǃ +Eǃ8n]1u]苴ˍ'U($D$D$D$D$D$D$ D$Ð&UH]U ]u}$vt]u}]Ð3FFD$D$4$HD$D$4$D$D$4$hD$D$4$ qU 38U ƅ+U :H  @ }8)D$$(k<$LP(k&vt_L$ |$D$(k$MME]}u]Í$(kd|$D$(k$C<$LP(kvU $T$E|$D$G(kMD$ $<$LP(kM>B$(kDP(k&$(kDP(kP<$LP(kM $LP(ket&USÃ@D$D$$m@u[]ǃ4(k[]G&UX]]u}E80;}uTU܉T$ U؉T$t$$u)8Ut܆t8vEǃ8]u}]É4$]u}]ǃ8ˍ8$(k8E랋 byǃ878 c4<t&@<pM<?D$(k4$ 'ǃ88c$T$D$(kM7ǃ8 T$D$(k $MCNEEf$T$D$(kMCwNEEuʍED$ED$ D$D$$ ]'UT$D$(k4$ u ǃ8 UEЉ$LP(kEN$T$D$(kLCN EET$D$(k $LCuNEEEUԋ}ǐ< < t< t<=z<$芿fHM=T t t t >ȍv΁0a$T$D$(kK@83cT$D$(k4$K {NEEUT$ UT$$T$N7U,T$D$(k4$ u ǃ8Ut&NEEDUT$UT$ T$$T$LUT$D$(k4$3 vǃ8gNEEUT$ UT$$T$Mt,&8c0P$T$D$(kI 8 cT$D$\(k $IEEUԉD$ED$D$ |$$D$?Ml[0tꋻPuD$(k4$ǃ8(p=D$$fǃ4(k<  t tUT$UT$D$(kT$ D$ $T$dNqUfT$D$(k4$@ǃ8 1T$D$(k $2H7ǃ8 (ǃ4D$(k4$D$ǃ8EUT$UT$T$T$ $T$T$kWxUmT$D$(k4$Wǃ8HD$(k4$*ǃ8D$D$D$T$D$D$ D$$Eǃ8E  < vzt&U(]] uu}\$4$ۉu]u}]ËH tb]u}]ÍvUWVS,U2eM 11ۋ,'uN 8,;]  8(kũ,t]uЋ 벋D$D$(kU $MU䋆,< tmǂ, e ..1;] ǂ,Zu<;} tn 1,[^_]ǂ,&D$D$(kU $葸U,;} ǂ,u,1[^_]ÉU$PP(kUzD$h(k4$DaU8uu]}N,9}u^(MѤ}w $$T$t$|$ u)Åut2蝤M䋱 $$T$t$|$ 躤u)9Oމ؋u]}]ÐU8]]u}s,0$E8~TSt8D$ |$D$$Lqte1uD]u}]f뿍&ED$ (k$]C]u}]Éu}C0u]]&ED$8(k$C]u}]Ít&'U8]]u}s,0$MU~dS=Lȸt;L$ |$D$$Sp4$E*tC]Ћu}]É뼍&$D$ (k`B]uЋ}]跢D$ET$$u}tMtu}C0u]]UD$8(k$AaUS]C,CCC 6C S$[]Ív'UX]E ]}us,D$$J(k(tE<$D$t<$LP(kts$E蹴NjE$TED$|$ \$04$D$=umu8E9tkUz)ljȉZz]u}]ù]ȋu}]ËUt$\$D$T$ $M>Mf$ELP(kM뷉Mԉ$LP(k]CCCC S$M냍t&'UED$E D$E$ U1WVS\u V,UċU]ȁÌ]]]ȋV+N }ԉ߉ӉMЁ?u^UԉD$\$$?FE$LP(kFEU1]ԋMBHF 9~rUԃ]{ UuUȋL$ UċF D$$D$?U4$T$V4E1ɉ^ 99M{~ Mпt,N $PP(k^ N$\$L$4]1FE^ ]1t&UĉL$ T$UȋF D$M$D$}EDžE}hht$LP(kdžhD$$0(k`lE؉hEED$(k$L$LP(kdžLE\t$LP(kdž\PtD$(k$Jdž\Et EED$(k$#D$(k$8EUE|[^_]ËU$(kfǃED$D$D$ D$D$D$ D$4$TEE@(kEG(kvǃEU(kEc(kEl(kfEr(kt&Ew(kt&E}(kt&ǃEȆ(k{Eȏ(koD$(k$7E+fD$(k$7E+t&}D$}(k$ED$(k$&(kEEEaEPt$LP(kdžPT$$(kiEP?EE|[^_]D$(k$EN@LU2vEEED$(k$#(kEEȉD$a6E+t&D$(k$`;-Xt$LP(kdžXT$$(khEXD$h$@P(kEE䉃4D$(k$t\D$(k$5E+D$@(k${5E+P$(kD$gE\:E[EP`Eȉ|$ D$E(kT$#(kEEȉD$E$E6EЅt%UЋED$a(kT$$E U#(kM}D$o(kҋUDЅɋMUUDЅ}؉UUDЉUUҋUDЅɉUUDЅEE؉UUE؋ET$UD$ET$ D$ED$E؉D$E$Ek}t}tE$D$EEE4$D$E+}Eǃ} }}Eǃ D$D$(k$+D$ED$D$ t$$&1ɃD$EL$D$D$ D$D$ D$4$E䃃H(@, LL$D$$4${*DEE! ǃHEEЉUEU܋EỦUȋU)EŰ}UԋEỦUȋU)EŨ}}Eǃ D$D$(k$t$E؉D$dD$E$D$ED$D$ t$$eU U[M1(SE؋U܃ EȉUt EЋUԉEȉŰEȋUD$(kD$ET$ $8tED$|(k$|tE}uCǃxtpU܃EtMǃHEEOD$(k$uD$(kE$t\udtk1EуMD$(k$ND$(kǃHǃD$(k$^0}EE&vUWVS<} {M$D$HP(k9]St] T$$L$ >$F^F ÍC9sCEEԉ׉ʋEgDUD$4$L$ ML$MыU=9E}D${(k$/MD$(k $ /]t $LP(kLJLJ<[^_]Ët $LP(kLJLJ<[^_]É}D$j(k$.bM)u䃹 u ]~a>$BFMԉ^F ÍC9Mԋ9KM䋇EM}ԉх]U)Bt t $LP(kLJ1LJ<[^_]ËU]rt }ԉыU<$u $MPP(kML$t$$MMt $LP(kMM1t&ωы]넋}ԉrUED$ D$D$0$qZ1t-u&t!UtED$$Ív'UWVSø$c]ȉ$UE\$D$<$D$ &E)ÅUD$ dD$$T$GSUЉt$ \$<$T$UԉT$i!tUD$(kEĉ$_%UȋEątUȉ$LP(kEă\[^_]ÍU1E(kU-t&MȅtӋUȉEĉ$LP(kEă\[^_]ËEȅt Uȉ$LP(kUD$(k|$$$uuD$ D$(kD$<$q%cUD$D$D$8T$D$D$ D$<$ETEUD$(kEĉ$F$Eă\[^_]ÐU6WVS}UEMԋEM ELM MċM (DM MLJEEEUMPMD$(kL$ ML$Mԉ $_(Mԋt$LP(kMǁ M$(kL$ML$U D$ D$D$(k<$ $ELP(kEd(kj(kE`(kDE̅Һh(k$(kE̸l(kDEMT$ D$L$ML$=UEU MD$(k $El(k MԻl(kD$(k $xMD$(k $p(kD[l(kHl(kT$Ủ\$D$(kDD$EȉT$ 4$D$EЉD$UȀ:MЉE $LP(kEt$MD$ (kE $!EČ[^_]Ét$<${uD$(k4$GuM D$ |$4$L$ML$uMDf軁 $L$\$ $T$ہM)^MԃpM11EEEMM̉MMԁM&SEȅH( $L$\$ $T$HM)NыMĉT$ D$D$ $NMED$@+EЉ<$L$MĉD$ L$Q{cEoEЃ}_U UR)EU}|4~,M1ۉ<$EMEt?Č*[^_]Ã}w΋MEEM1ۉ<$u}?vMԁt<$fEMԋMDlDMD$D$(k $#MԋMD,t&MԻD$h(k $%vE1f1MԋP,LJ1EfEMԋMԋ=D$D$$(k $ UtMԋt LJMDČ8[^_]Í&4$ELP(kEČ[^_]ÍMԻD$(k $E]1ɉ}σ9}2{ ]uMԋqMԃM̉t$ L$MD$ $~M< R< JuD$$y(kMM̉L$賑tMԁMD$$(kL$聑tMԸtnMD$$(kL$NtnED$ D$$茌EUM]̃19}}1fM̉D$L$M $tjMD$(kD$(k $AE늋Mt$ D$L$M̉L$Mԉ $ eMD$@(k $Č8[^_]ËMUT$ D$<$L$E<yEMD$(kD$ $9 xt&MD$(kD$(k $utiMD$(k $M $E&MD$ D$D$ $HČ1[^_]ËMD$(kD$(k $ME܉D$D$(kL$ M̉ $MԋMDHt $LP(kMLJHǁ0 $D$T(kM1ǁ\E$LP(kEMD$(k $MEDEԉ}EEtxM1EDMMMԋDL9E$(kD$KE]Љ$LP(k4$LP(kxE{MԉD$D$((k $_<;U UEE3EԋUǀED$ (k$M)ȉD$E̋Mx EUT$ <$)ȉD$ẼD$7EMD$(kD$ $4EM<$D$MUED$(kMT$ UԉD$$EM)ȉ)EU}|}wE4MD$(k $EE'U1]]u}t u ]u}]ËUǃD$ $D$D$]u}]ÐUWǃt$ g)k$LP(kGt $LP(kGt$[8u.u61tft}Ív7tf뽍vUH]]uuȉ}C 4$D$|(kD$ D$ /CD$ Ct$D$C$u9$$g)kC$`g)k]1u}]t&=i)kׅus׺EЉS륍&'USS T$S$T$6C []U(]Éu։$D$0t$D$(kD$D$ $*]u]U(u։}lj]t $LP(kt!t$C $LP(k]}u]Í&'U1]É'U]Ít&'U1]É'U]Ít&'U1]É'UE])'U(]]uu }1$ uJǃttWt]u}]É&fǃ]u}]Í&t(k댍v(ksv'U8Euu }]EEt^C $$g)kKC M$`g)kEtCE[UEU1]u}]Ð+s}T$$t$|$ HsSHEtK9C҉Sv[CЋU1CL$$ ]u}]ÐCȋE(kN벍v'U1]É'UWVS] Uut$\$$*~#E\$t$$D$ "e[^_]Íut$\$$*E1<E3D1D rUuBtUȉ$D$|(kD$ EED$ *D$D$@P(kƋEUEǂF ǂǂ8E1tftUVEF$EF(EF,EF0EF4EF8EF*U\$t$$T$ e[^_]ËEpUE54$xg)kDg)kU$D$*U\$D$(kD$ $EUȉD$ ET$D$$‹E;i)kD$E$*U\$D$(kT$ UD$$1fF ~ 7g)k0fU]ÐUWVS,UEM u¼Hh)kE‰Eu t $ӅuD$t$$(k΂1t6F~Hh)ku7t&UtzuTU1&,[^_]ÃtΉ$ӅuU|$T$U$-uɋU뾋UD$ (k$Y, [^_]ËUD$(k$7U tt&UWVSL} EEE8H $}ԋ}ԅG I(kDׅDϋ>ED$ED$ t$L$$MuWUt$LP(kUu I(kJ(kT$$Q(kDD$>E$LP(kL[^_]Í8T } t$LP(k}G L1[^_]Í}|$}|$t$ L$T$$oUtt$LP(kUM J(kT$$Q(kɹI(kDD$>E$LP(kUԉB L[^_]fU]ÐUVS HˈU ڈUP XM HU ӈ]X PM]$ ȈEUt$$ [^]Ít&UuEu }}]h8\$|$4$D$ EڃG\$D$4$D$ Eڃ\$|$4$D$ h]u}]ÍvUWVS} ]<$N} )|$Zt$<$TT4$hD$D$~Mt$\$D$ $l(ka$Ct$D$ D$$l(kCCļ[^_]1OvUWVSM $Mn|<Ɖ<$PP(kMøt`0tt&DCC9uu4$"|$\$4$Et$$E@@$LP(k1Č[^_]ÐUVS ED$ED$E EE$!juXuU}BvD$D$(k4$ |t*4$ LP(kED$(k$ [^]ÍFD$D$(k${uFV V V ЋUBFBFB 4$LP(k뜋E D$t(k$J 념&US$D$p(kD$l(kD$hD$dD$`D$\D$XD$TD$PD$LD$HD$DD$@D$<D$8D$4D$0D$,D$(D$$D$ D$D$D$D$D$ D$(kD$ E\$D$ $D$ED$ BiĄ[]É'UWVS ]u DžSƅt 1tftD$\4$y)\T\p\$xlD$<$c<$xhttѥpѥlѥhCUD$D$$EKDžK D$ D$4$L$PDžDžDžEET$LD$E$D$Z(kD$D$ }$uыEh$D$jh !%tDJD+D$i$Ƅh/i$(k s !%tDJD+$<$D$D$ D$D$X(k<$ h !%tDJD+$hT$<$D$U <$1t$w &>D$Z(kD$D$ }&$Fu$(k KD$ D$<$ D$D$X(k<$ ڋ !%tDJD)ډ$<$\$D$ <$D$D$X(kg $Qg$q<$D$D$; <$D$D$X(k# $ g$-<$D$D$ <$D$D$X(k $f$<$T$D$ <$D$D$X(k &T$<$D$ { <$1t$ >D$Z(kD$D$ }G$s uыEDžuserDžnamefDž="D$$f!сကtDʍPDɃ)",reD Balm=B"T$$0f !%tDJD)",no@nce=@"D \$$e !%tDJD)",cn@oncef@="D$D $|e !%tDJD)",nc@=D$D$'e !%tDJD),dig@est-@uri=@ "hD$D $d !%tDJD)",re@spon@se=GD$D $edE D$t$D$ED$ E$HSvU]&U8E]]uu}} EE$t$EEE܋E D$st]u}]fE܉}}uu]]EEEEE ]tt&U]ÐU18uu]] }t>t t;u ]u}]Ét$$^ct]u}]D$*4$bEt2D$.4$ibt@D$.$Pbt9}v \$4$bt1hD$D$p(k4$wcuD$.$aEtƋE<$D$btE))9|E\$4$)D$'ctu}))ωL$|$4$c1%e)k%e)k%e)k%e)k% e)k%$e)k%(e)k%,e)k%0e)k%4e)k%8e)k% fL$$Q D$,1l$4\$0fl$4T5F\$$C tXtl$$M@;H s AM@t;t$,uŋl$4\$0D$$@+)t$,9t$$VD$$@@$ D$, 1l$4\$0fL$41F\$$C tX$tl$$M@;H(s AM@t;t$,uƋl$4\$0D$$@t)t$,t$$VD$$$ w;D$,t{t$,|$( v NEEvt$,|$(ˋL$$A%;D$( $F(k\D$$PD$DD$<$G T$8W/L$,OD$(T$$B8Z$E )D$T$$B$tt$,|$(T$,D$$ ֋T$<)~@;|$8v|$8)|$8)L$$A@D$0y D$<9B9D$< D$4D$< Ш D$4L$4@ 1l$4l$< L@9rl$4L$<L$0+t$0T$0;|$0t1l$0ՊT@9ul$0|$v*|$$W1T$$v ,Z$A(k|$$҈l$(+\$Tt$$D$4@$G(kD$TL$Tl$()t$$҉V@D$$l$()Ӌ|$0T$$ftzpG|$0zhD$<$G T$8W/L$,OD$(T$$B8Z<\$@\$<$f |$<$ml$8$+[\$,\$$[8\$(t$$^< džt$$F @1vD$,Mt$,|$(=t$l$@$UL$$Amt$l$@$5L$$A$F(k|$$"f)V4mFDT$0VHt$,D$(D$|D$(D$}D$D$|D$C$CS\$$҉T$\D$TD$dHD$`#D$(L$TЍT$0PT$4fPD$4L$dL$T9swD$,t$Tt$,|$,|$dCNED$(ED$(#D$`D$\T$,T$0PT$4fPD$4 89wt$,t$TL$TL$dl$()l$(D$4)Ë|$Tt$$҉V@|$0+T$0.@M$A(kt$$|D$,t$(%$G@(kD$$K|$$GL(kGT GP)kGX$g$A(kt$$ET$0T$l$L$$A$ t$$FfD$(D$|D$(D$}D$(D$~D$(D$D$D$|D$C$d C\$$N\$$S@1ۃ$D$(t$$D$($F(k|$$D$(D$|D$(D$}D$D$|D$\$$C$ CS19s:t$(ىT$\ v0HUE9rt$(ˋT$\L$,l$()ӋT$0?T$0t$$LVnT$(T$\l$(|$$WHD$,9s3tt$(ىT$\HUE9rt$(ˋT$\|$(L$,t$\|$()1ɋt$\+t$T1D$(t$$D$DV\$$C t T$(D$(\$$1D$(B\$8\$@1D$()lj|$T$$B$ D$$@hD$0‰QD$,|$$?fpp$@<(kD$<$G T$8W/L$,OD$(F8^ t?k {D$DЉC C{k ukF 1,[^_]f> uKD$D$$T$T$T$L$DL$$9FT$t멍v럐둍vD$T$t$@t@tP B01fffUWVST$('Bj8p<X8X8x<ݍL$t<A9t A9uGh8@<@h11۽$f)ȉC9s%t T8t1C9rf$Hhj:1ۅtBw=$)ȉC9t"w8t1C9uދ$Hh)Z߉:ZZr@(@,@0@BBBH@@ @@ @8@<0HlHPHLǀǀZr 1[^_]AfA fx<+׍vJ0nHh[^_]Ív@h1뛍vD$t@t8 t1Ð@<øfUWVSt$4L$0 ^F V$D$D$V($ЉŅC4D$K$D$F($V |$0fSL09s>Sl)0UltK$s4ljE4D$0h1[^_]Ð9w)0ULSP)0UP땍v1i븸뱉l$F($V$fD$t@tǀÐffD$t8Pt7 t t1ÍvJ@f+J@øøUWVS1DŽ$ 퍜$$39u1v1t$t3>uu򉼬E u1v1t$t3>uf@I!΍TJfr) tt$(΃t.9v|$WЃG|$J!T$()#T$H!‹t$<frJ) uL@Al$4l$< v@+J!֍TJfr) t΋l$4t$P΃9v |$WЍK9G|$˺z!NjT$PT$T)T$+T$L9T$Tt$T)։t$49t$XsT$`T$0T$lT$,T$\+T$4T$0L$49L$()L$(L$`+L$t$\)+t$P)t$8~|$p|$GL$4L$PL$l|$4 D$hL$p  L$hN9D$t|$9|$pL$tL$tL$h1ɉl$hl$f||A9L$Pwl$ht$t$l|$4+|$lT$lL$l9L$4t1ɉl$PōvD DA9ul$Pt$4t$T$+T$T|$(v2L$t$(NJBABAwL$t$(L$(t6J|$O|$(RWt$f|$WG|$T$9T$st$ 9t$fT$))ˉپN!ƍB$D$@G D$)Ѓ$B\$ +D$$GD$p8H<Ą[^_]Ív t7T$ x|$wWKЃ|$$F&)k|$3v$G&)kT$T$+T$Tt$(l$4D$TD$JHJHxjJHw܉D$t$(l$4D$TMJ|$O@RWt${T$49T$,t$,t$\+T$4T$0+L$,L$49L$()L$(L$`+L$$)+t$P)t$8NL$tL$AL$|L$4L$hL$p |$4 D$xL$t L$| L$xN9L$|D$L$9L$tL$L$L$x1ɉl$xl$D$tDDA9L$hwl$xD$tt$t$pL$4+L$pL$hT$pL$p9L$4t1ɉl$pŊD DA9L$hul$pT$T$4T$4t$(9t$,T$,)։t$($+T$,T$PL$ыt$@|$, ‰֋T$8 ʃ!֋T$89D$y9|$8T$T$1ҋ|$844B9T$DwL$4L$@t$,+t$@|$d|$lT$@9T$,t1҉D$DDB9uD$T$4T$,T$+T$TWЃ|$q|$LT$,+T$4T$09L$()L$(L$`+L$t$,)+t$P)t$8~|$p|$GL$4L$PL$l|$4 D$hL$p  L$hN9D$t|$9|$pL$tL$tL$h1ɉl$hl$||A9L$Pwl$ht$t$l|$4+|$lT$lL$l9L$41ɉl$PŊD DA9uG|$O|$C׋T$0|$$F&)k5t$,L$4|$lr|$4t$X|$4t$뀋t$4t$ht$q%i)kffffffS(,E)k$D$$,E)k$D$(E)k$xD$D$D$D$D$D$0$ËD$$Z,E)kD$$I$(E)kp([ÐD$0$g)k(É[Ív'D$ $1ÐD$$tt t&T$(D$D$ T$$  'S=dP(kD$$t dP(ktt;[ ()k()ktftЃ()ku[ D$(D$D$D$ $4 f1ÐD$Ít&'D$ÐSg)kD$\$$D$$&)k@D$ 8D$ \$D$g)k@$ UWVSLL$ A)kT$A)k1ۋB9rzG9 9u4$  [A)k<C T$$E CA)kT$g)kD$D8T$$Ӄ T$RD$8A)kD$T$4$Ӄ RD$8u2D$4$D$D$D$L[^_]fT$$g)k뭍t&@tɋD$0l$ g)kl$ D$@D$D$$$ӃD$4$D$D$D$yD$8@ttD$ l$ D$D$0D$D$$$ӃL[^_]Ív@D$0 A)kT$D$@D$D$$L$ $g)kT$Dg)k$d')kD$t&1?A)kD8D$E$0')kD$yt$$')kit$D$$0')kQA)ktÍUWVS\A)k@ A)k)čD$A)k ()k- ()k R ()k()k=()k()k* ()kC ()ksJs{$k$kM t>t$$')kEOe[^_]û ()k ()ksS$k$kUȍUv ()krԡA)k11}̅뭃 ;5A)k}A)k؋tD$|$@$g)k EȉD$ A)kD$E؉D$Ẻ$g)k뗍v ()k3?K/$kfHM)ց$kUMĹ ()k08H$k)MčUĹ]뿋M$k)UĉMĹ>A)kCD$C@$0')kD$D$$')k`P(kt fС`P(kP@`P(ku Ít&S@@(kt$t@@(kvu$$(k"[1ÍC@@(kuƍ& A)ktÍt&A)k딐LhP(k\$D$(k$D$>uBF=Hi)k$fERF$}Q|$ D$D$(k$ԋ/F<tr <t*<uH6D$ҥ(k$謋4D$֥(k$蚋"D$ܥ(k$舋D$(k$v<#t <'t+<Et$D$(k$F~D$(k$"H7tu&D$(k$&D$(k$T$D$(k$ӊF9uw+7FD$(k$T$貊 9uwՃ}tD$(k$芊e[^_]UWVS<8Eԍ9ƃvƃ9v @ $ED$ D$D$0$Xi)kyi)kD$,(k<$D$÷0D$ D$\$$Xi)kyi)kD$,(k<$D$賃e[^_]UWVSL <+$"B<#tL<'<1߃D$$D$ \$D$D$֍~:(1߃D$$D$ \$D$D$#֍~D$D$ D$(kD$$;D$ t$\$$Xi)ky i)kD$,(kD$$S><$uD$D$'D$D$ D$(kD$$菛1э<wlhD$ $D$D$ (kD$)hD$5T$D$D$ D$/(k$[q)D$3D$D$ D$8(k$FD$ D$\$$Xi)ky i)kD$,(kD$$ր>4$ze[^_]ÐffUU$$kÐ @(k)(k0(k(k5(k0(k5(k4(k4(kP@(kN@Dlibgcj-13.dll_Jv_RegisterClassesCouldn't open file %sCan't open %s for writingCan't get the size of %sContent-Length: %lld Accept-ranges: bytes Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT Can't get the size of file.failed to resume file:// transferFILE*a(k`$k@$k$k$kP$tI%c%c==%c%c%c=%c%c%c%cABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/%s:%d%255[^:]:%d:%255sResolve %s found illegal! Added %s:%d:%s to DNS cache %2lld:%02lld:%02lld%3lldd %02lldh%7lldd%5lld%4lldk%2lld.%0lldM%4lldM%2lld.%0lldG%4lldG%4lldT%4lldP 4$kP4$k4$k4$k4$k#5$k 4$kV5$k04$k3$kCallback aborted** Resuming transfer from byte position %lld %% Total %% Received %% Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed %3lld %s %3lld %s %3lld %s %s %s %s %s %s %s $tIzDrb-application/octet-stream}F$kI$kI$kpI$kH$kH$kK$kwK$kVK$k}F$kJ$kJ$kXJ$k8J$kI$kI$kJ$k}F$k}F$k@I$kContent-Type: multipart/form-data%s; boundary=%s --%s Content-Disposition: form-data; name="" Content-Type: multipart/mixed, boundary=%s --%s Content-Disposition: attachment; filename="%s"; filename="%s" Content-Type: %s %s couldn't open file "%s" --%s-- --%s-- image/gifimage/jpegtext/plaintext/htmlapplication/xml.gife(k.jpgf(k.jpegf(k.txtf(k.htmlf(k.xml&f(k0123456789abcdefTRUEFALSE/unknown.#HttpOnly_%s%s%s %s %s %s %lld %s %sReplacedAdded%1023[^; =]=%4999[^; ]securehttponlydomainskipped cookie with illegal dotcount domain: %s skipped cookie with bad tailmatch domain: %s versionmax-ageexpires %s cookie %s="%s" for domain %s, path %s, expire %lld path ^$k]$k]$k`]$k_$k^$k`^$knone-rSet-Cookie:w# Netscape HTTP Cookie File # http://curl.haxx.se/docs/http-cookies.html # This file was generated by libcurl! Edit at your own risk. # # Fatal libcurl error %s WARNING: failed to save cookies in %s Rewind stream after send NTLM send, close instead of sending %lld bytes Empty reply from serverAvoided giant realloc for header (max is %d)!Failed to alloc memory for big header!HTTP/RTSP/Proxy-BasicProxyServerDigestNTLMProxy-authorization:Authorization:%s:%s%sAuthorization: Basic %s %s auth using %s with user '%s' The requested URL returned error: %dAuthentication problem. Ignoring this. Ignoring duplicate digest auth header. 100-continueExpect:Expect: 100-continue Host:Content-Type:Content-LengthConnection%s Invalid TIMEVALUE%s, %02d %s %4d %02d:%02d:%02d GMTIf-Modified-Since: %s If-Unmodified-Since: %s Last-Modified: %s HEADGETTransfer-Encoding: chunked ][Accept: */* 1.11.0Proxy-Connection: Keep-Alive ; User-Agent:Referer:Referer: %s Cookie:Accept-Encoding:TE:Accept-Encoding: %s Transfer-Encoding:Connection:%s, TE TE: gzip Connection: TE TE: gzip chunkedHost: %s%s%s Host: %s%s%s:%hu ftp://;type=;type=%cAccept:Could not seek streamCould only read %lld bytes from the inputFile already completely uploadedContent-Range:Range:Range: bytes=%s Content-Range: bytes 0-%lld/%lld Content-Range: bytes %s%lld/%lld Content-Range: bytes %s/%lld %s ftp://%s:%s@%sProxy-Connection:%s HTTP/%s %s%s%s%s%s%s%s%s%s%s%sCookie: %s%s=%s%s%s Content-Length: 0 Failed sending POST requestInternal HTTP POST error!Content-Length:Content-Length: %lld Could not get Content-Type header line!Failed sending PUT requestContent-Type: application/x-www-form-urlencoded 0 %x Failed sending HTTP POST requestFailed sending HTTP requestupload completely sent off: %lld out of %lld bytes Chunky upload is not supported by HTTP 1.0no chunk, no close, no size. Assume close to signal end Keep sending data to get tossed away! HTTP error before end of send, stop sending HTTP/%d.%d %3d HTTP %3d RTSP/%d.%d %3dHTTPThe requested URL returned error: %sHTTP 1.0, assume close after body Maximum file size exceededNegative content-length: %lld, closing after transfer keep-aliveHTTP/1.0 proxy connection set to keep alive! closeHTTP/1.1 proxy connection set close! HTTP/1.0 connection set to keep alive! identitydeflategzipx-gzipcompressx-compressContent-Encoding:Set-Cookie:Last-Modified:WWW-Authenticate:Proxy-authenticate:Location:HTTPSJr(k$kx$k0|$k t$k z$kt$kp(k$kx$k0|$kt$kPPOSTPUTs(ks(k s(kk(k[%s %s %s]%sFailed writing body (%zu != %zu)Failed writing headerRecv failure: %sSend failure: %sfromtos(ks(ks(ks(kHeaderDatas(ks(ks(ks(k* < > { } { } USER %sPWDPBSZ %dQUITFailure sending QUIT command: %sMaximum file size exceededftp server doesn't support SIZE Offset (%lld) was beyond file size (%lld)File already completely downloaded Instructs server to resume from offset %lld REST %lldRETR %s%sConnect data stream passively got positive EPSV response, but can't connect. Disabling EPSV PASVAPPE %sSTOR %sSIZE %sCould not seek streamFailed to read dataFile already completely uploaded getsockname() failed: %sfailed to resolve the address provided to PORT: %sbind(port=%hu) on non-local address failed: %s bind(port=%hu) failed: %sbind() failed, we ran out of ports!socket failure: %s%s |%d|%s|%hu|Failure sending EPRT command: %s,%d,%d%s %sFailure sending PORT command: %sError accept()ing server connectConnection accepted from server Doing the SSL/TLS handshake on the data stream /no memoryUploading to a URL without a file name!Request has same path as previous transfer ;type=%c%c%c%u%cWeirdly formatted EPSV reply%d,%d,%d,%d,%d,%dCouldn't interpret the 227-responseSkips %d.%d.%d.%d for data connection, uses %s instead %d.%d.%d.%ddisabling EPSV usage Bad PASV/EPSV response: %03dCan't resolve proxy host %s:%huCan't resolve new host %s:%huConnecting to %s (%s) port %d unknown proxytype option given$k$kl$kl$k$k`$k$k`$kTYPE %cMDTM %sCWD %sLISTNLSTPRET %sPRET STOR %sPRET RETR %sREST %d %s%s%sFTP response timeoutFTP response aborted due to select/poll error: %dWe got a 421 - timeout! Checking for server connect Accept timeout occurred while waiting server connectThere is negative response in cache while serv connect Error while waiting for server connectReady to accept data connection from server Ctrl conn has data while waiting for data conn Preparing for accepting server on data port Got a %03d ftp-server response when 220 was expectedunsupported parameter to CURLOPT_FTPSSLAUTH: %dAUTH %sPASS %sACCT %sACCT requested but none availableAccess denied: %03dACCT rejected by server: %03dPROT %cCCCFailed to clear the command channel (CCC)SYSTEntry path is '%s' Failed to figure out path OS/400SITE NAMEFMT 1QUOT command failed with %03dMKD %sServer denied you to change to the given directoryFailed to MKD dir: %03d%04d%02d%02d%02d%02d%02d%04d%02d%02d %02d:%02d:%02d GMTLast-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT unsupported MDTM reply format Given file does not existThe requested document is not new enough The requested document is not old enough Skipping time comparison Couldn't set desired modeGot a %03d response code instead of the assumed 200 Content-Length: %lld Couldn't use RESTPRET command not accepted: %03ddisabling EPRT usage Failed to do PORTConnect data stream actively bytesMaxdownload = %lld Getting file with size: %lld Data conn was not available immediately RETR response: %03dFailed FTP upload: %0d $k%k`%k!%k!%k5%k.$k$k$k$k$k$k$k$k$k$kr$k%k%k$k$k$k$k$k$k$kq$kq$k0$k$k$k$k$kw$kWildcard - Parsing started Wildcard - START of "%s" Wildcard - "%s" skipped by user %k%k%k6%k%kRemembering we are in dir "%s" ABORFailure sending ABOR command: %scontrol connection looks deadpartial download completed, closing connection server did not report OK, got %dUploaded unaligned file size (%lld out of %lld bytes)Received only partial file: %lld bytesNo data was received!QUOT string not accepted: %s@%k(%k(%k(%k(%k(%k(%k(%k(%k@%k@%k(%k@%k@%k(%k(%k(%k@%k@%k@%k(%k(%k(%k@%k(%k@%k(%k(%k(%k(%k@%k(%k(%k(%k(%k(%k@%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k@%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k(%k@%kFTPS(k$k`%k%k %k$k@$k%k $k $k$k$k gFTPd(k$k`%k%k %k$k@$k%k $k $k$k$kfSSLTLSEPRTPORTEPSVPASVd(k$kx$k(k$kx$k%llu-IDN support not present, can't parse Unicode domains *, CURL_CA_BUNDLEClosing connection #%ld Connection (#%ld) was killed to make room (holds %ld) This connection did not fit in the connection cache fileLDAPDICTftphttpIMAP/][%15[^:]:%[^ ]%15[^ :]://%[^ /?]%[^ ]%[^ /?]%[^ ] malformedFTP.DICT.LDAP.IMAP.%255[^:@]:%255[^@]:%255[^@]%25Invalid IPv6 address format Protocol %s not supported or disabled in libcurl%s://%smemory shortageno_proxyNO_PROXYhttp_proxyall_proxyALL_PROXYsocks5hsocks5socks4asocks4socks[%*45[0123456789abcdefABCDEF:.]%cIPv6 numerical address used in URL without brackets;type=%c%s://%s%s%s:%hu%s%s%sPort number too large: %luCouldn't find host %s in the _netrc file; using defaults anonymousftp@example.comConnection #%ld seems to be dead! Connection #%ld hasn't finished name resolve, can't reuse Connection #%ld isn't open enough, can't reuse Re-using existing connection! (#%ld) with host %s Couldn't resolve host '%s'Couldn't resolve proxy '%s'://deflate, gzipALLSESSFLUSHSet-Cookie:CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!Connected to %s (%s) port %ld (#%ld) proxy User-Agent: %s About to connect() to %s%s port %ld (#%ld) Connection #%ld to host %s left intact  (kr(k`r(k(k (k (k(k(k@a(k(k(k`(k (k(k(k(k@(k(kdefault!./MATCH:/M:/FIND:lookup word is missing CLIENT libcurl 7.28.1 MATCH %s %s %s QUIT Failed sending DICT request/DEFINE:/D:/LOOKUP:CLIENT libcurl 7.28.1 DEFINE %s %s QUIT CLIENT libcurl 7.28.1 %s QUIT DICT(k %kD @Operation too slow. Less than %ld bytes/sec transferred the last %ld seconds,Microsoft Corporation.LDAP local: LDAP Vendor = %s ; LDAP Version = %d LDAP local: %s LDAPoneonetreebasesubsubtreeLDAP local: %sLDAP local: Cannot connect to %s:%huLDAP local: ldap_simple_bind_s %sLDAP remote: %sDN: : ;binaryThere are more than %d entries cleartextLDAP local: trying to establish %s connection encryptedތ(kЉ%kErrorClient helloClient keyClient finishedServer helloServer verifyServer finishedRequest CERTClient CERTHello requestCERTServer key exchangeClient key exchangeCERT verifyFinishedUnknownTLS alert, TLS handshake, TLS app data, TLS change cipher, TLS Unknown, SSLv%c, %s%s (%d): ߗ%k%k%k՗%k%k˗%k%k%k%k%k%k%k%k%k%k%k%k%k%k%ku%kk%k%k%ka%kW%k%k%k%kM%k%s:%s(%s) %s: %s %02x:SSL_write() returned SYSCALL, errno = %dSSL_write() error: %sSSL_write() return error %dGMT%04d-%02d-%02d %02d:%02d:%02d %sPEMDERENGP12 Signature: %s SignatureSSL read: %s, errno %d(critical), %s: %s %s %s%c--- Certificate chain %2d Subject: %s Subject Issuer: %s Issuer Version: %lu (0x%lx) %lxVersion Serial Number: %ld (0x%lx) %02x%c Serial Number: %s Serial Number Start date: %s Start date Expire date: %s Expire date Unable to load public key RSA Public Key (%d bits) %dRSA Public Keyrsanedpqdmp1dmq1iqmpdsagpriv_keypub_keydh%s CertSSL: couldn't get peer certificate!Server certificate: SSL: couldn't get X509-subject! subject: %s start date: %s expire date: %s subjectAltName: %s matched subjectAltName does not match %s ssluse.cSSL: illegal cert name fieldSSL: unable to obtain common name from peer certificateSSL: certificate subject name '%s' does not match target host name '%s' common name: %s (matched) SSL: couldn't get X509-issuer name! issuer: %s rSSL: Unable to open issuer cert (%s)SSL: Unable to read issuer cert (%s)SSL: Certificate issuer check failed (%s) SSL certificate issuer check ok (%s) SSL certificate verify result: %s (%ld) SSL certificate verify result: %s (%ld), continuing anyway. SSL certificate verify ok. Signature Algorithm: %s Signature Algorithm Public Key Algorithm: %s Public Key Algorithmlibcurl is now using a weak random seed! noneSSL certificate problem, verify that the CA cert is OK.SSL connection timeoutOpenSSL was built without SSLv2 supportSSL: couldn't create a context: %sSSL: couldn't set callback! SSL: couldn't set callback argument! unable to use client certificate (no key found or wrong pass phrase?)LOAD_CERT_CTRLssl engine does not support loading certificatesssl engine cannot load client cert with id '%s' [%s]ssl engine didn't initialized the certificate properly.unable to set client certificatecrypto engine not set, can't load certificaterbcould not open PKCS12 file '%s'error reading PKCS12 file '%s'could not parse PKCS12 file, check password, OpenSSL error %sunable to use private key from PKCS12 file '%s'private key from PKCS12 file '%s' does not match certificate in same filecannot add certificate to certificate chaincannot add certificate to client CA listnot supported file type '%s' for certificateunable to set private key file: '%s' type %sfailed to load private key from crypto engineunable to set private keycrypto engine not set, can't load private keyfile type P12 for private key not supportednot supported file type for private keyunable to create an SSL structurePrivate key does not match the certificate public keyfailed setting cipher listerror setting certificate verify locations: CAfile: %s CApath: %serror setting certificate verify locations, continuing anyway: successfully set certificate verify locations: CAfile: %s CApath: %s error loading CRL file: %ssuccessfully load CRL file: CRLfile: %s error signaled by ssl ctx callbackSSL: couldn't create a context (handle)!WARNING: failed to configure server name indication (SNI) TLS extension SSL: SSL_set_session failed: %sSSL re-using session ID SSL: SSL_set_fd failed: %sselect/poll on SSL socket, errno: %dSSL certificate problem: %sUnknown SSL protocol error in connection to %s:%ld %s%sSSL connection using %s old SSL session ID is stale, removing failed to store ssl sessionSSL Engine '%s' not foundFailed to initialise SSL Engine '%s': %sset default crypto engine '%s' set default crypto engine '%s' failedSSL_ERROR_WANT_READ SSL_ERROR_WANT_WRITE SSL shutdown timeoutOpenSSL/%lx.%lx.%lx%s zlib/%s7.28.1i386-pc-win32dictfileftpftpsgopherhttphttpsimapimapsldappop3pop3srtspsmtpsmtpstelnettftp>(kC(kH(kL(kQ(kX(k](kc(kh(kn(ks(kx(k~(k(k(k(k(k%%%02X%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%ld.%ld%k%k%kC%k%k%k%k6%k%k%k%k'%k'%k%k'%k'%k'%k'%k'%k'%k%k%k'%k%k%k'%k8%kU%kU%kU%kU%kU%kU%kU%kU%kU%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k%k'%k'%k%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k'%k%k'%k'%k'%k%k'%k'%k'%k'%k%k'%k'%k'%k'%k'%k'%k'%k'%k %kc%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k0%k%k%k%k%k%k%kP%ke%k%k%k%k%k%k%k%k%kD%k%k%kP%k%k%k%k%k%k0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz(nil)(nil)EXOPLDONTDOWONTWILL%s IAC %s %s IAC %d %s %s %s %s %s %d %s %d %d Sending data failed (%d)SENTRCVD%s IAC SB (terminated by %s %u %s%d, not IAC SE!) (Empty suboption?)%s (unsupported)%d (unknown)Width: %hu ; Height: %hu IS SEND INFO/REPLY NAME "%s" , = %c %.2x %c%c%c%c%s%c%c%c%c%c%c%127[^,],%127s%c%s%c%s%c%cUSER,%s%127[^= ]%*[ =]%255sTTYPEXDISPLOCNEW_ENVWS%hu%*[xX]%huSyntax error in telnet option: %sBINARYUnknown telnet option %sWSAStartup failed (%d)insufficient winsock version to support telnetfailed to load WS2_32.DLL (%d)WSACreateEventfailed to find WSACreateEvent function (%d)WSACloseEventfailed to find WSACloseEvent function (%d)WSAEventSelectfailed to find WSAEventSelect function (%d)WSAEnumNetworkEventsfailed to find WSAEnumNetworkEvents function (%d)WSACreateEvent failed (%d)WSAEnumNetworkEvents failed (%d)In SUBOPTION processing, RCVDTime-outWSACloseEvent failed (%d)FreeLibrary(wsock2) failed (%d)WS2_32.DLL&kp&k<&k&k.&k&kt&kG&k&k&k&k&k&k&k&kTELNET(k%k%k@@ECHORCPSUPPRESS GO AHEADNAMESTATUSTIMING MARKRCTENAOLNAOPNAOCRDNAOHTSNAOHTDNAOFFDNAOVTSNAOVTDNAOLFDEXTEND ASCIILOGOUTBYTE MACRODE TERMINALSUPDUPSUPDUP OUTPUTSEND LOCATIONTERM TYPEEND OF RECORDTACACS UIDOUTPUT MARKINGTTYLOC3270 REGIMEX3 PADNAWSTERM SPEEDLFLOWLINEMODEOLD-ENVIRONAUTHENTICATIONENCRYPTNEW-ENVIRON(kd(ki(km(k(k(k(k(k(k(k(k(k(k(k©(kɩ(kЩ(kש(k(k(k(k(k (k(k%(k/(k=(kH(kW(k^(kj(kq(kv(k(k(k`(k(k(k(k(kEOFSUSPABORTEORSENOPDMARKBRKIPAOAYTECELGASBIAC`(kd(ki(ko(ks(kv(kz(k(k(k(k(k(k(k(k(k(k(k(k(k(kHOMEr machineloginpassword_netrc\%s%s%s&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&kw&k&kh&kY&kJ&k;&k,&k&k&k &k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k}&k&k&k&kn&k&k&k&k&k_&k&k&k&k&k&k&k&kt&k&k&k&k&k_&kJ&k;&k&k,&k&k&k&k&k&k&k&k&k&k&k&k&k&k&k operation aborted by callbackread function returned funny value%x%sseek callback returned error %dthe ioctl callback returned %d ioctl callback returned error %dnecessary data rewind wasn't possibleThe requested document is not new enough The requested document is not old enough select/poll returned errorRewinding stream by : %zd bytes on url %s (zero-length body) Excess found in a non pipelined read: excess = %zd url = %s (zero-length body) Ignoring the response-body HTTP server doesn't seem to support byte ranges. Cannot resume.Failed writing dataProblem (%d) in the Chunked-Encoded dataLeftovers after chunking: %zu bytes Rewinding %zu bytes Rewinding stream by : %zu bytes on url %s (size = %lld, maxdownload = %lld, bytecount = %lld, nread = %zd) Excess found in a non pipelined read: excess = %zu, size = %lld, maxdownload = %lld, bytecount = %lld Unrecognized content encoding type. libcurl understands `identity', `deflate' and `gzip' content encodings.we are done reading and this is set to close, stop send Failed to alloc scratch buffer!We are completely uploaded and fine Done waiting for 100-continue Operation timed out after %ld milliseconds with %lld out of %lld bytes receivedOperation timed out after %ld milliseconds with %lld bytes receivedtransfer closed with %lld bytes remaining to readtransfer closed with outstanding read data remainingNo URL set!HEADGETMaximum (%ld) redirects followed%15[^?&/:]://%c//Issue another request to this URL: '%s' Violate RFC 2616/10.3.2 and switch from POST to GET Violate RFC 2616/10.3.3 and switch from POST to GET Disables POST, goes with %s Re-used connection seems dead, get a new one Connection died, retrying a fresh connect unspecified error %d%sCONNECT_ONLY is required!Failed to get recent socketalnumalphaxdigitprintgraphspaceblankupperlowerdigitFL&kK&kK&kVK&kL&k -> total rwx-tTsS0123456789-APM0123456789:\&kZ&k\&kZ&k6[&k[&k\&kE\&k`\&kZ&kY&kE_&k_&k^&k_&k^&kS^&kp_&k]&k7^&k]&kb]&k0]&k]&kt`&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kk`&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kb`&kY`&kP`&kZ&kZ&kZ&kZ&kZ&kZ&kZ&kG`&kZ&kZ&kZ&k>`&kZ&kZ&k`&kUnrecognized content encoding type. libcurl understands `identity', `deflate' and `gzip' content encodings.f&kh&kh&kh&kh&kg&kg&kg&kg&k0g&kg&kg&kgetpeername() failed with errno %d: %sgetsockname() failed with errno %d: %sssrem inet_ntop() failed with errno %d: %sssloc inet_ntop() failed with errno %d: %ssa_addr inet_ntop() failed with errno %d: %s Trying %s... Could not set TCP_NODELAY: %s TCP_NODELAY set Failed to set SO_KEEPALIVE on fd %d if!host!Local Interface %s is ip %s using address family %i Name '%s' family %i resolved to '%s' family %i Local port: %hu Bind to local port %hu failed, trying next bind failed with errno %d: %sFailed to connect to %s: %sconnected Timeout %s Couldn't bind to '%s'proxyhostConnection time-outconnect() timed out!couldn't connect to %s at %s:%dAfter %ldms connect time, move on! Connection failed Failed connect to %s:%ld; %s&k&kԑ&k&k&k&k&kp&kp&k@&k#&k#&k#&kInternal error clearing splay node = %d Internal error removing splay node = %d Pipe broke: handle 0x%p, url = %s In state %d with no easy_conn, bail out! Resolving timed out after %ld millisecondsConnection timed out after %ld millisecondsOperation timed out after %ld milliseconds with %lld out of %lld bytes received1&kq&k &k&k&k &kc&k&k&k?&k|&k,&k&k%&kۡ&k&ka&kDelayed kill of easy handle %p Error while processing content unencoding: %sError while processing content unencoding: Unknown failure within decompression software.1.2.71.2.0.46&k&k&kp&k`&kP&k%02xDigestnoncestaletruerealmopaqueqop,authauth-intalgorithmMD5-sessMD5Proxy-%32ld%s:%s:%s%s:%.*s%s:%s%s:%s:%08x:%s:%s:%s%sAuthorization: Digest username="%s", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=%08x, qop=%s, response="%s"%sAuthorization: Digest username="%s", realm="%s", nonce="%s", uri="%s", response="%s"%s, opaque="%s"%s, algorithm="%s"'k'k'k\'k'k'k\@01234567890123456789abcdef0123456789ABCDEFUnknown errorCURLSHcode unknownCall interruptedBad fileBad accessBad argumentInvalid argumentsOut of file descriptorsCall would blockBlocking call in progressDescriptor is not a socketNeed destination addressBad message sizeBad protocolProtocol option is unsupportedProtocol is unsupportedSocket is unsupportedOperation not supportedAddress family not supportedProtocol family not supportedAddress already in useAddress not availableNetwork downNetwork unreachableNetwork has been resetConnection was abortedConnection was resetNo buffer spaceSocket is already connectedSocket is not connectedSocket has been shut downToo many referencesTimed outConnection refusedLoop??Name too longHost downHost unreachableNot emptyProcess limit reachedToo many usersBad quotaSomething is staleRemote errorDisconnectedWinsock library is not readyWinsock library not initialisedWinsock version not supportedHost not foundHost not found, try againUnrecoverable error in call to nameserverNo data record of requested typeUnknown error %d (%#x)No errorUnsupported protocolFailed initializationURL using bad/illegal format or missing URLA requested feature, protocol or option was not found built-in in this libcurl due to a build-time decision.Couldn't resolve proxy nameCouldn't resolve host nameCouldn't connect to serverFTP: weird server replyAccess denied to remote resourceFTP: The server failed to connect to data portFTP: unknown PASS replyFTP: Accepting server connect has timed outFTP: unknown PASV replyFTP: unknown 227 response formatFTP: can't figure out the host in the PASV responseFTP: couldn't set file typeTransferred a partial fileFTP: couldn't retrieve (RETR failed) the specified fileQuote command returned errorHTTP response code said errorFailed writing received data to disk/applicationUpload failed (at start/before it took off)Failed to open/read local data from file/applicationOut of memoryTimeout was reachedFTP: command PORT failedFTP: command REST failedRequested range was not delivered by the serverInternal problem setting up the POSTSSL connect errorCouldn't resume downloadCouldn't read a file:// fileLDAP: cannot bindLDAP: search failedA required function in the library was not foundOperation was aborted by an application callbackA libcurl function was given a bad argumentFailed binding local connection endNumber of redirects hit maximum amountAn unknown option was passed in to libcurlMalformed telnet optionSSL peer certificate or SSH remote key was not OKServer returned nothing (no headers, no data)SSL crypto engine not foundCan not set SSL crypto engine as defaultFailed sending data to the peerFailure when receiving data from the peerProblem with the local SSL certificateCouldn't use specified SSL cipherPeer certificate cannot be authenticated with given CA certificatesUnrecognized or bad HTTP Content or Transfer-EncodingInvalid LDAP URLMaximum file size exceededRequested SSL level failedSend failed since rewinding of the data stream failedFailed to initialise SSL crypto engineLogin deniedTFTP: File Not FoundTFTP: Access ViolationDisk full or allocation exceededTFTP: Illegal operationTFTP: Unknown transfer IDRemote file already existsTFTP: No such userConversion failedCaller must register CURLOPT_CONV_ callback optionsProblem with the SSL CA cert (path? access rights?)Remote file not foundError in the SSH layerFailed to shut down the SSL connectionSocket not ready for send/recvFailed to load CRL file (path? access rights?, format?)Issuer check against peer certificate failedFTP: The server did not accept the PRET command.RTSP CSeq mismatch or invalid CSeqRTSP session errorUnable to parse FTP file listChunk callback failed(k(k(k(k(k(k(k(k(k(k(kG(k`(k(k(k(k(k(k(k4(k(kl(k(k(k(k(k(k=(kK(k(k_(kx(k(k(k(k(k(k(k1(kC(k(kX(k(k(k(k(k(k(k8(kc(k(k|(k(k(k(k((kH(k(kt(k(k(k(k:(kK(kf(k(k(k(k(k(k(k=(kU(ko(k(k(k(k(k(k.(kH(kp(k(k(k(k,(kO(kb(k(kPlease call curl_multi_perform() soonInvalid multi handleInvalid easy handleInternal errorInvalid socket argumentUnknown option(k(k*(k?(k=(kS(kb(kz(kUnknown share optionShare currently in useInvalid share handleFeature not enabled in this library(k(k(k(k=(k(k%d.%d.%d.%d%lx%31[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]%02d:%02d:%02d%02d:%02dJanFebMarAprMayJunJulAugSepOctNovDec(k(k(k(k(k(k(k(k(k(k(k(kMonTueWedThuFriSatSun0(k4(k8(k<(k@(kD(kH(kMondayTuesdayWednesdayThursdayFridaySaturdaySundayh(ko(kw(k(k(k(k(kGMTUTCWETBSTWAT<ASTADTEST,EDTCSThCDT,MSTMDThPSTPDTYSTYDTHSTXHDTCATXAHSTXNTIDLWCETMETMEWTMESTCESTMESZFWTFSTEETWAST\WADT CCT JSTEASTEADTlGSTNZT0NZST0NZDTIDLE0A<BxCDE,FhGHIKXLMNOPLQRST\U VWXlY0Z;Zx0NReceived last DATA packet block %d again. Received unexpected DATA packet block %d, expecting block %d %sTimeout waiting for block %d ACK. Retries = %d tftp_rx: internal errorConnection time-outset timeouts for state %d; Total %ld, retry %d maxtry %d Connected for receive%s Received ACK for block %d, expecting %d tftp_tx: giving up waiting for block %d acktftp_tx: internal error, event: %iConnected for transmitbind() failed; %s;mode=octetnetascii%s%c%s%c%lldtsize%dblksizetimeouttftp_send_first: internal errorTFTP finishedInternal state machine error'k'k'k'k'k'k'k'kReceived too short packetMalformed ACK packet, rejectinggot option=(%s) value=(%s) invalid blocksize value in OACK packetblksize is larger than max supported%s (%d)blksize is smaller than min supportedserver requested blksize larger than allocated%s (%ld)requestedblksize parsed from OACK%s (%d) %s (%d) tsize parsed from OACK%s (%ld) invalid tsize -:%s:- value in OACK packetInternal error: Unexpected packetTFTP response timeoutTFTP(k'k'k`'k 'k'k'kP'kP'k'kE@aConnection time-out%hu.%hu.%hu.%huFailed to resolve "%s" for SOCKS4 connect.Failed to send SOCKS4 connect request.Failed to receive SOCKS4 connect request ack.SOCKS4 reply has wrong version, version should be 4.SOCKS4%s request granted. Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d), request rejected or failed.Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d), request rejected because SOCKS server cannot connect to identd on the client.Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d), request rejected because the client program and identd report different user-ids.Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d), Unknown.SOCKS5: server resolving disabled for hostnames of length > 255 [actual len=%zu] SOCKS5: no connection hereSOCKS5: connection timeoutSOCKS5: error occurred during connectionUnable to send initial SOCKS5 request.SOCKS5 nothing to readSOCKS5 read timeoutSOCKS5 read error occurredUnable to receive initial SOCKS5 response.Received invalid version in initial SOCKS5 response.Failed to send SOCKS5 sub-negotiation request.Unable to receive SOCKS5 sub-negotiation response.User was rejected by the SOCKS5 server (%d %d).SOCKS5 GSSAPI per-message authentication is not supported.No authentication method was acceptable. (It is quite likely that the SOCKS5 server wanted a username/password, since none was supplied to the server on this connection.)No authentication method was acceptable.Undocumented SOCKS5 mode attempted to be used by server.%d Failed to resolve "%s" for SOCKS5 connect.Failed to send SOCKS5 connect request.Failed to receive SOCKS5 connect request ack.SOCKS5 reply has wrong version, version should be 5.Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)Can't complete SOCKS5 connection to %s:%d. (%d)Can't complete SOCKS5 connection to %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)4'k4'k4'k4'k4'k4'k4'k4'k4'k4'k4'k4'kw4'kp4'kg4'k`4'kW4'kP4'kG4'k@4'k74'k04'k'4'k 4'k4'k4'k%s LOGIN %s %s%s LOGOUT** Got unexpected imap-server response%s STARTTLSAccess denied. %cSTARTTLS denied. %cFound %llu bytes to download Filesize left: %lld Select failed%s FETCH 1 BODY[TEXT]%E'k"F'kE'kE'k%E'kE'kPE'kINBOX%s SELECT %sIMAPS?(k='kG'k='k@'k@'kI'k?'k?'k@?'k0eIMAP(k='kG'k='k@'k@'kI'k?'k?'k@?'kdABCD(k(k(k (k(k$kx$k?(k$kx$kUSER %sQUIT-ERRUSERAPOPSASLLOGINPLAINCRAM-MD5DIGEST-MD5GSSAPIEXTERNALNTLM+OKLISTRETR%s %sCAPA . Got unexpected pop3-server responseSTLSSTARTTLS denied. %cNo known SASL authentication mechanisms supported! %02xAPOP %s %sNo known authentication types supported! Access denied. %c%sAccess denied: %dpopAuthentication failed: %dPASS %sAUTH %sX'k['kZ'k`\'k['k['k[Z'kY'krY'k2Z'kX'kX'k]X'k]X'kd['k;['kX'kPOP3S(kJ'k@R'k`J'kL'kL'kT'kpL'kpL'kK'kEPOP3(kJ'k@R'k`J'kL'kL'kT'kpL'kpL'kK'kn@D(k$kx$kn(k$kx$kEHLO %sRCPT TO:%sRCPT TO:<%s>QUITlocalhostSIZEAUTH LOGINPLAINCRAM-MD5DIGEST-MD5GSSAPIEXTERNALNTLMNo known authentication mechanisms supported! AUTH %s %sAUTH %s . <>%s<%s>%lldMAIL FROM:%sMAIL FROM:%s AUTH=%sMAIL FROM:%s AUTH=%s SIZE=%sMAIL FROM:%s SIZE=%sGot unexpected smtp-server response: %dHELO %sRemote access denied: %dSTARTTLSSTARTTLS denied. %cAccess denied: %dsmtpAuthentication failed: %dMAIL failed: %dRCPT failed: %dDATAq'kv'kv'ku'kt'kq'ku'kJu'kTv'kPt'kt'ks'kNs'ks'kr'kr'kEr'kr'k r'kFailed to alloc scratch buffer!SMTPS(k0b'k m'kk'kd'k@d'k z'k d'k d'kc'kESMTP(k0b'k m'kk'kd'k@d'k z'k d'k d'kc'kD(k$kx$k(k$kx$kserver response timeoutselect/poll error%s response reading failedExcessive server response line length received, %zd bytes. Stripping The CSeq of this request %ld did not match the response %ldGot an RTP Receive with a CSeq of %ld *Accept: application/sdp RECORDSET_PARAMETERGET_PARAMETERTEARDOWNPAUSEPLAYSETUPANNOUNCEDESCRIBEOPTIONSGot invalid RTSP request: RTSPREQ_NONEGot invalid RTSP request: RTSPREQ_LASTRefusing to issue an RTSP request [%s] without a session ID.Transport:Transport: %s Refusing to issue an RTSP SETUP without a Transport: header.Accept:Accept-Encoding:Accept-Encoding: %s User-Agent:Referer:Referer: %s Range:Range: %s CSeq:CSeq cannot be set as a custom header.Session:Session ID cannot be set as a custom header.%s %s RTSP/1.0 CSeq: %ld Session: %s %s%s%s%s%s%sContent-Length:Content-Length: %lld Content-Type:Content-Type: text/parameters Content-Type: application/sdp Failed sending RTSP request'k'k'k'kЈ'k'k'k'k'k'ku'k 'k0'kCannot write a 0 size RTP packet.Cannot pause RTPFailed writing RTP dataGot an error writing an RTP packet: %ldUnable to read the CSeq header: [%s]Got RTSP Session ID Line [%s], but wanted ID [%s]Got a blank Session IDRTSP1(k'k`'k'k'kЄ'k'k*6\Failed sending Gopher request GOPHER(k0'kF1.01.1][Proxy-Connection: Keep-Alive Establish HTTP proxy tunnel to %s:%hu %s:%huCONNECT%s%s%s:%huHost:Host: %s Proxy-Connection:User-Agent:CONNECT %s HTTP/%s %s%s%s%s Failed sending CONNECT to proxyProxy CONNECT aborted due to timeoutProxy CONNECT aborted due to select/poll errorProxy CONNECT abortedchunk reading DONE Read %zd bytes of chunk, continue Ignore %lld bytes of response-body %zd bytes of chunk left Proxy CONNECT followed by %zd bytes of opaque data. Data ignored (known bug #39)WWW-Authenticate:Proxy-authenticate:Content-Length:closeConnection:chunkedTransfer-Encoding:CONNECT responded chunked HTTP/1.%d %dTUNNEL_STATE switched to: %d Received HTTP code %d from proxy after CONNECTProxy replied OK to CONNECT request %dCould not resolve %s: %s; %sproxyhostinit_resolve_thread() failed for %s; %s getaddrinfo() failed for %s:%d; %s NTLMNTLM handshake rejected NTLM handshake failure (internal error) Proxy-%sAuthorization: NTLM %s KGS!@#$%NTLM handshake failure (unhandled condition) NTLMSSPNTLM handshake failure (bad type-2 message) NTLMSSP%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%sgethostname() failed, continuing without! NTLMSSP%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%cuser + domain + host name too big=%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02xnonce="realm="algorithm=md5-sess:%02x0123456789abcdefxn--1.2.7need dictionarystream endfile errorstream errordata errorinsufficient memorybuffer errorincompatible version(k(k(k(k(k(k(k(k(k(kincorrect header checkunknown compression methodinvalid window sizeunknown header flags setheader crc mismatchinvalid block typeinvalid stored block lengthstoo many length or distance symbolsinvalid code lengths setinvalid bit length repeatinvalid code -- missing end-of-blockinvalid literal/lengths setinvalid distances setinvalid literal/length codeinvalid distance codeinvalid distance too far backincorrect data checkincorrect length check|'k\'k'k'kD'k'k'kD'k'k'k<'k~'k'k'kL'k'k'kh'k'k$'k.'kD'kh'k8'k'k'k'k$'k'kP'k'k`Psp0  ` @ X ;x8 h( H T+t4  d$ D \ S|< l,  L R#r2  b" B Z Cz: j*  J V@3v6 f& F  ^ c~> n. N `Qq1  a! A Y ;y9 i)  I U+u5  e% E ] S}= m-  M S#s3  c# C [ C{; k+  K W@3w7 g' G  _ c? o/ O `Psp0  ` @ X ;x8 h( H T+t4  d$ D \ S|< l,  L R#r2  b" B Z Cz: j*  J V@3v6 f& F  ^ c~> n. N `Qq1  a! A Y ;y9 i)  I U+u5  e% E ] S}= m-  M S#s3  c# C [ C{; k+  K W@3w7 g' G  _ c? o/ O A@!  @a`10  @     0w,aQ mjp5c飕d2yҗ+L |~-d jHqA}mQDžӃVlkdzbeO\lcc=  n;^iLA`rqgjm Zjz  ' }Dңhi]Wbgeq6lknv+ӉZzJgo߹ホCՎ`~ѡ8ROggW?K6H+ L J6`zA`Ugn1yiFafo%6hRw G "/&U;( Z+j\1е,[d&c윣ju m ?6grWJz+{8 Ғ |! ӆBhn[&wowGZpj;f\ eibkaElx TN³9a&g`MGiIwn>JjѮZf @;7SŞϲG0򽽊º0S$6к)WTg#.zfJah]+o*7 Z-A1b62S-+ldEw}ZVǖAOIъ OM~-QJ#SpxAaU׮.7׵Y-6]]wll?AԞZ͢$ Faw$eڪ]]FD(koipvk19Z* ,  m86F߲]qTp0ek*1u4yީ%8S1bSWĔՖk1**ykʬHpo].*F6fcTT"eM©g0&):{ϼkZ> 8$,52F*sw1pHkQ6Fzw]cN̵J #pAF]#l8?1(BOgT~yUbL8^#ܖTZ1ObbSyOIV~P-{b-R4٠~^eGnHl/Su6: #jT$+e?yHf'*b#ٽЧ ?&~?$pi;FBzw[keZ~7 Sv8H 3?r$7jnԄYFܨ |OQ;օ U d S - =G\ p&Gw)` /a߫i5&LsZ<#0zMzFM8,9; :R:(q-v,.7/pXqYs3r%w+OQvrtEux܉~OK }!b|tyBxʠz{.lD~m8onlk[wjR1h58ib?mcf+aQ`צedd"fig HINSKyuJcO NZLݘMFGN@E$DD2AsX@*IBCPhTg3U>uW ַVS:R|P~Q9ZS [fYX4])\ZEo^m/_5qϱ٥s\ۼqދ!K7 kfֶԁ-b3Πjp]$^'~*I@VW<âM˟ŏ{ tDCm-@wm.B+(铜>Td"ŀǼϭ~8y$owJ1}05_K^ iϏ은BI#ƈdX܁T̓cQ: rՆ⩗ fn|xK)o%ƭ/3vUuA?)C:|sĵ@͂ Ͳ;bIUeh"׻_HS1޼^Z4eg Wb27_k%8ם(ŊO}do׸Jj3wVcXWP0qB{߭gCru&op-?'Bs ưGz>2[Ȏg; i8P/ _Y=чe:ZO?(3wwXR @hQ+ğH*0"ZOWoI}@mNП5+#*'G| AH=XX?#1jvʬ`p^Y<L~i/{kHwâ hs)aLoD~Pf7VM'(@ﰤ ہg9x+n&;f?/X)T`D1 ߨMߒ.FgTp'Hq/L0UEc?kǃh6ry7]P\@TN%s7@'>$!AxUʰ\3;Y^U~PGl!;b F2ȂpԞ(Q_V:1X: n3 m:@/)IJNv"2x+ٗ Kx.HҥfAj^y9*O]#kM`~b_R 7zFh!1߈Vc0a"j6nS Nr)Υ{t*F8#vufz`rs"WG9^EMvc΍&DAdQy/4Aڱ&S֚E biLQ<6'5P..T&q]w4.6IE? v\[YI>U!lDa>Ԫ΋ϩ7~8A]&nv|oY yKiw\¹9~$ 66nQfq>,o,IӔ 渱{I .H>C-Yn馑gQz tafw0a, Qmpjc5dۈ2yܸو L+~|-dj qHA}mԵQӅlVdkbze\Ocl=c ;n Li^`Agqr<KG k5Blۻ֬@2lE\u ϫ=Y&0Q:Qa!V#Ϻ(_ ٲ $/o|XhLaf-=vAq *q3xɢ4 j m=-dlc\kkQlabe0bNl{WeP|b-I|LeMaX:QΣtԻ0JߥA=ؕפmCij4ngF`D-s3 L_ |Pq<'A  Wh% of a^)ɘИ"רY=. \;l  tҚG9w&sc d; mj>zjZ '}DhibW]egl6qnkv+zZgJoC`֣ѓ~8ORѻgWg?H6K +گ L6JAz``ègU1nFiyaf%oҠRh6 w G"U&/ź; (+Z\j1,ٞ[ޮd°c&ujm 6?rgWJz{+ 8Ҏվ | !Bhݳڃn&[owGwZjpf; \ebiaklE x NT9§g&a`IiGM>nwۮjJZ@ f7;𩼮S޻G0齽ʺŠS0$6TW)#gfz.aJ]h*o+ 7 Z-1A26b+-Sdl}wEVZOAي»IˬO ~M-JQS#xpaA.U7Y-۩6˚w]]llA?Z$㧲F waރ$Ųe]]DFok(vpi91k *Z  ,8mF6]pTqke0*1¶u4%y<8syjHA}X*ݹ1SbSW§ٖծ1k**kypH]oF*.f6TTcMe"¤0g)&Ůޟ:{kZ >8,$5*F21wsHpQkzF6c]wN̵ׄJ# pȄA#]F8l1?(gOB~TUyLbˁ8#^TO1ZbbySIOP~V{-b-4R^~Ge­lHnuS/:6# $Tj?e+y䏼Hf*'˼Ѝb# &??~p$iBF;[wzek~ZS 7H8v ?3$rj7nFY |OQ; U dؓS - \G=&pGw`)/ ai5&sL <:R=Pe6^X7}o5641W0ճ2k3$k%'1&-[#bML"'{ "!$*x(+)`F(> q-q,v.Ț/7pqXsYr3w%vQO+tru՛E~xKO} |b!ytxBz{l.m~Do8nkljw[h1Ri85bcm?a+f`Qeddf"giH IKSNJuyOcN LZMݥFĚGE@ND$A2D@XsBI*CThPU3gWu>V SR:P|Q~Z9[ SYfX]4\)^oEZ_/m5qs<\kg2z &J8 좞V`a/6i\lU,zB\uHƒ=&FW A+Ox]`غ7W>9q߳!7Kk ֩fض-bѠ3pj$]^Ĝ'*~@IWVÕ<ӂMʏş{ Dt͆mC-@mw+B.(>dT"ş~Ϝ8yo$w1J}50K_ ^ϋiBۉI#dXфTQc:r Р fΫnx|)Ko%3/uUv?A)ġ:C|sд@͉ ;IbeU"hH_S1ފZ^ھ4ge ȋbW72%k_ܝ8Ŵ(}OodJֿjw3XcVPW0Bq{gǧurCo&p-?О'sB zGɠ2>[ ;g/P8i_ Y=嗇e:ϏOZw3(?RXw@ Qh+HZ"0*WOIo@}m5N#+'*GA |􏒨HX=#?X1vjʨ`^pYL'!$UxAׯ3\Y;U^GP~b;!lڇF 2p(ԐQV_:X1: 3n :m@I)/NJ2"v+x xKH.jAf^O*9y]#Mk~`bю_޶ Rz7hFм!10cV"ajحn6 SrN){t*8Fv#fu`zrϮsɛW"G9E^vMcD&dA/yQA4S&ֿ EbLil!>aDƋΪ~7A8n&]|vYoᡱ Kyi׫w¡\~9$66 Qnf>q,o,ӹI 散 I{.C>HnY-Qg̰t zfa inflate 1.2.7 Copyright 1995-2012 Mark Adler  #+3;CScs !1Aa  0@`ND@@invalid distance too far backinvalid distance codeinvalid literal/length code(kMingw-w64 runtime failure: Address %p has no image-section VirtualQuery failed for %d bytes at address %p VirtualProtect failed with code 0x%x Unknown pseudo relocation protocol version %d. Unknown pseudo relocation bit size %d. D)kA)kmsvcrt.dllzR| 0|DpXplp zR| TPAA AAC@k AA AAB E AA AAC M AA AAC p AA AAD  <TWAA AAC0 AA AAB HlAA C0  AAD _  AAC H  AAB ,TZAC  AA H AC 0H_AA @ AA Q AB lt AA AAF AA AAC  AA AAD i AA AAC (WAC G AD <LAA AAC@Z AA AAC 6TAAA AAC( AA AAA @ AA AAD *< NAA AAC0 AA AAB L.`LzR| < NAA AAF?AA AA\0Pp$AA AAC( AA AAB EAA AAzR| LxLAA AA A AAA p A AAA HltAA AAh A AAA ZA AAHAA AAh A AAA ZA AAzR|  AA AAFm AA AAA  AA AAA [ AA AAA Q AA AAA zR| @PX AA AAF AA AAD PvR;;(PQR0B C@B@F`AHPEH0A 0F`O`X`p0@`?@pppЗ жP@P`@ `;@<>@>0RRRRRRRR SS*S;SNSaSmSzSSSSSSSSSTTT*T8TNT`TsTTTTTTTTU(UkJkZkxkkkkkkkkll$l,l4l>lJlVl`lnl|llllllllllllmmmm&m.m6m>mFmNmVm`mjmtm~mmmmmmmmmmmmmn nnn(n2nkJkZkxkkkkkkkkll$l,l4l>lJlVl`lnl|llllllllllllmmmm&m.m6m>mFmNmVm`mjmtm~mmmmmmmmmmmmmn nnn(n2n.h(Licensehttp://curl.haxx.se/docs/copyright.htmlDVarFileInfo$Translation p0"0N0_0d000011%121F1K1q111111122!2H2O2Z2222I44444445b566-7G77}89==!>(>I>? t00&1I111:2&344444495D5W5i55555T6s666667 77,757B7Y7d7O88$9I9Y9b99g:>z?0( 00;11#2\222 3T336}8G:\;c?@d0V2 3T3h333^4~445555-66667-7789::;$;;>A>>?1?O??????P11122m2222$3C3333/4e4445H5c555]6666y77799::%:5:E:N:b:j:::::::::;8;J;Bj>>>X?^?`xC0S0c0s00001111I223 444255556666P7777 88888L9k9t999!:::: ;;;;<c>>> ??pX0[0?1Q1x11111t255678'9399:;d;;<= >z>>>>>>> ??,?X?b???t00911}333?4]444w5m66677@88888E9L:`:h:::4;;;'H>>>$?@?l???????0000001 1311]223:3333#4@4444 555I5\555556h67)7Y7q77778&88888A999 ::: :T::;;>>6>C>{>>>>O??d+0F111!2A2Y2q2y22333445X5v55M6666?7T7i77888^99;;;"<*>?B?J?u??d191A12.2c2223C333=4444,5H5w55556;7k778Z88909O99x::;;s;;;;{k>>?6?m??`@0-1:112z2J3 55555627q77777(8G8899F9R9l9999:;;H;< <(>?`0D1Y22:3b3r3y33(4445+5:5a55555B7M7778O889)9H99:D;s;;n<<=[=>5> ?F??t0x000O112s2 3&3j3334w4~4455555!6P6r6z697778M8~89&9u9999>:::::b;z;;;<<<=7=O==?D345-5U666677'8R8}8889$9[;:>8?_? x0S001Z111222i33334505M5j555555656R6o66666z777^88@9p9:::;";K;R;g;<%=^==*>=> ?@?0ds1182L2v33334{4444556777888888F9p9:.:A:{::";Z;~;;;R<="=z==:>Q>}>>?@`50P0001121O1b1111E222332335T5e5555566^9r999%:E:@;F;W;];;; <=??PH=0x001/1111 2)2F222I3333 44677!8>8m88889{999`a88[9=>p0$2245U5555<6h669<:<<<=??0i0H222X34)4Z4t44445595l555(656E6l6667e88888899{999::9:W::::;x;;;=i>>>>?'?5?????? 080000K1j1112%222 3_333 4<4[4o4444445'5\56677777777777888$8)8I8N8X8b8l8v888889R9 :':n:::m;;;;<<>>??x000:1|1122$3B3Y333434g4{4444`555 66X6l66677778H89O:p:::::<<==>>>C?_?????010[0w00001-1I1s111112E2a22222;3p334B4W44555H6x66"7A7777898c889,9q::N;; <5>???|#0+0D00}111122G3333:4r4444@5*6a666,777777+838T8x9997:Z:u:::;;T;o;;;,?N?\????????L0G112;33N444444515?5V5d55"6o;;<2<+=z==>>>7>?>F>>?40(0H00]4n4}405W5J66666J7l799;>>2? @0J22!445K7 8D888U9w999 :<<==>9>X>>"?G?k?z?0L000 1Y111112=4X4777;6;;?=?b?j????????????@l>0\0b0k0t0}00000000<3S34<44445k55u777w88=9t99::;u;;;Tf>>???P`00 1.1[1s111111223222'33333+445)56667i7,8d8}8h99R:::X<=}===>`(0003556L66r79:<<<\=pd00.0p0000121L111|2235_666Q7d777Z88i999:T:t::v;;;p>K?L000<1\1222 334E4455r677M8{88D9u9:+::::<<= >7>>,Q0Z014I56666!77p9::;;?u?(11>9:X:;;Z>???`B000-1m122 2N3333444556F7e8899::;;/;F;;;">>>2?M????040H0t0000111Q12(22223I3~3333,4A4k44444575e55J666666 77 8/88888819Q9:::g;<"<3>}>>>>?K???????000"0,060A0K0U0_0i0s0}00000000000 111<1F1e1o11111111Q33333*444n6V778+838b8>9p9997;b;vt><&181"556T8o8888F9]9t999999 :<=Z>>g???`p0$1202C2222394444 555677 888p99:&;M;d;;;;;:A>>???`00070?0012B2n2222[3h333/444l5566Q7]7e7777*8O8o8w888888 :r::R>k> H0044m556R7778!808m88:::;(;L;;;;f<<<=>>>?0l/000D1d1122=346666]7778Q8u888<9Q9m99::^:t::: ;;;;4<^>>>>>p???@X00)112i33455616666 7778888A:::;;;U;];;7<===>>>>?PX 0=0|00011133R444Z5t6v7Y8q88=9i99J:::%;S;;7<<<;>>> ?3??`p 0000#1q1112S2X2]2232333 55f5p556778N8888@9999@::;&;P;;Ch>>>>>s???pd0!040a00000000)1 2222;3334:45455166777(8g888`99:;; <&>??h?(090>12Y33P44455666737Z7~77778x888888888 9949^9u9999:T:^:::::;-;I;j;;;;<<=>A?h???+0C0f001112@23R33w44444I5556666678899b;;;;;; <{<7=c========>>E>T>d>l>>>>>>> ?=?h1 22233454445g555566966666o77778l88999::::;;;;;=Q===>??`000000#111112C2}222I3k33?4P4U4`4|44#545?5F5`5V777@88889K9Z999W:a?LG111)4/455566}7778B8Q8{888I999:j: ;;<2Q>r>X}55566646;6E6L6k6r6|666666666677!7(7G7N7X7_7|77777777%8<223389<>=U={=====>>>>>5?P?m???? (00T000?1b1w1~11111112.23282O2\2j2o2|2222222333#3<3C3c3z3333334:4V4j4~444444445"545b55555555666'6,6;6@6H6Q6[6a6j6{666666667E7T7Y7_7l7r77777778 88Q8Z8e8p8v888888[9i9p9u9999:&:-:G:Z:a:g::::::);;;C;R;c;;;:<@R>_>g>>?d?????@ .0D0P0 0 0@0D0H0L0P0`0`h@1H1L1T1p1333 33333 3$344444444444444444444H6T6`6l6x667777777p`2h2l2t2x22222222333333333333(9,9094989<9@9D9???????????????????????????`000 0000x0|0000111111111222 22222 2$2(2,2024282<2@2D2H2L2P2T2X2\2`2d2h2l2p2t2x2|222222222222222222222222222222222333 333 3$3(3,3034383<3@3D3H3P3333333333333333@4H4L4:`:d:h:l:p:t:x:|::::::::::;;>>?????????????????????????????,0?????????????????l0 00000 0$0(0,0004080<0@0D0H0L0P0T0X0\0`0d0h0l0p0t0x0|000000000000000000000000000000000111 11111 1$1(1,1014181<1@1D1H1L1l1p1t1x1|111111111111111111111111111111111222 22222 2$2(2,2024282<2@2D2H2L2P2T2X2\2`2d2h2l2p2t2x2|222222222222222222222222222222222333 33333 3$3(3,3034383<3@3D3H3L3P3T3X3\3`3d3h3l3p3t3x3|33333333333333333333333333333888888888999 999 9(9,9::::::::::::::::;;; ;;;;; ;$;(;,;0;4;8;<;@;D;H;L;P;T;X;\;;;;;;;;;;;;;;;;;;;;;8<<<@>>>>>>>>>>>>>>>>>>>>>>>??? ????? ?$?(?,?0?4?8?ljWRڪ 3hKhd jj tFhOhd PlV^_h5hd jj v_VW|$ 3t+NjhZhd jj Jlt%P;} lWQthahd jj tF_^_3^̡l̡l̡l̋D$l̋D$l̋D$l̡l̡l 1D$l̋D$l̋L$3D$AËD$L$H̃=lt3ËD$l̡l̡ltltЋT$3ɉ B T$3ɉ B̋L$T$V2;1us3^1+u"Bq+uBq+u BI+^̋D$L$@A̡l̋D$l̡lu% ̋D$} Ã)} VpסlP趧;~x ^Ë lVQ諧^ø =lVh l tb3ɀ8~WT$Rh 4V  uPPV  3҉D$T$ T$ D$_t /L$t$##. ^ËD$u2BL$MZf9uA<8PEu;H4t l  U l3ʼnElSVWP th P lll  ؅EPjjjS  zE=pFu MQVWjS tZE@E3h WfG ؍e_^[M3 ]ÃJЍe_^[M3 ]Ãe_^[M3 ]̸F l3ĉ$j` tCP t8$ $PQ @P  $3 Ë$ $RPL$ hQ Ƅ$ =sX~OVh j jD$PjjjjjjT$(VT$( V ^$3 jh L$ Qj  $3g ËD$ L$T$PQRh j j  @Vt$ }K=lt`Vxt!L$T$QRPD$PlV^h hShd lltL$T$QL$ RVQЃ^̡ltS\$Ul$VW|$$WSUj [D$$0t$(WSUj 0E _^][̃=luhhd jdjgjR3álthhd jj Сl=luEllu2thhd jj Ѓhhd jAjgj3Åthhd jj ЃVhhd j$ uhhd jAjgj3^hhd lFu"Vh hd jAjgjT3^álthhd jj ЃlWjPVu lQ謠OlWRǡ lthhd jj Ѓu$Fh!hd PlV _^G_^̋D$Pp̋D$L$PQx̋D$P(=htXL$tPT$tHD$ t@ ptpx| 339hu3ËL$V;tEt$ ;t=D$;t55|p tx ^3^̃=ht+L$t#D$t 3̃=ht+L$t#D$t 3̃=lu3_'D$L$T$ lD$ lL$ll l̋D$t3Ɂ=tpI# pD$t3ҁ=|J#xD$ t ̋L$ttЁp#ЉL$t|Ё#ЉD$ t ̋D$t3Ɂ=I# D$t̋L$tЁ#ЉD$t ̋D$t lD$tlD$ t lD$tlD$t lS\$3;3[álUVt$W|$ h;tQVWSQ lЃVWSl t jVWSUЃ_^][̡lVt$tjVЃVl^t jjЃS\$3;3[álUVt$W|$ h;tQVWSQ lЃVWStl t jVWSUЃ_^][VW|$ ǍPI@uL$+‹T$QR@Pf +Au_^Ul$uD$L$T$ PQR3 ]S\$[3]álVt$W|$t jVWSjUЃVWSU| lD$tjVWSPUыD$,_^[]S\$uD$L$T$PQR [W|$~;|$}_3[álUl$ VtL$ jUQWjSЃT$ URWt t!D$PSV L$$QS&SltT$ jURWVSЃ^]_[̡lVt$tjVЃVl^t jjЃVt$t-ltjVЃVlt jjЃD$ hh, P ^̡lt̡lt3Vt$NFFt PV+^̸v V5mhh< jj lD$ $'mm3mmmD$P=mtL$Qhl9tRhh< jj hh< jj hh< jj %mT$4RhlC8m8mt/=mt&-mu mhh< jj chh< jj M^ÍI&{&8'& 3mta$VPh&h< jjmuL$Qhl#u3h+h< jj^̋D$m̡m̋D$iiɻEV4+^̋D$VPE~iiɻE4+ƃ^̸ 39mte$VPmL$QRQ t@W~tmGWP衞F~FtGV._^̸v QShh< jj emD$PG=mtL$QhlltRhh< jj hh< jj hh< jj %mT$4Rhlv8mVhh< jj hh< jXtj=mu&hp(h(藜mu V;VjD$L$ T$FmVPN V^F tFhh< jj "^mt.=mt%)mu mhh< jj hh< jj [3̸ V3~.Shh< jj mD$Pt95mtL$QhltRhh< jj @hh< jj -hh< jj %mT$8Rhl8mhh< jj hh< jj mt.=mt%)mu mhh< jj hh< jj |[^̸V V3.8Shh< jj BmD$P$95mtL$QhlJtRhh< jj hh< jj hh< jj %mT$8RhlT8mhh< jj t uuhh< jj nmt.=mt%)mu mhh< jj 8hh< jj "[^̸ D$0W|$$VjDhh< j$su!WDhh< jj = mu/h@h@(葘 muWVmD$0L$4T$,>FN VtFP83FFm;muFF@mmtj FFL$QmF tT$RP誙tF @ mVP葘tx tH IP(hh< jj mt/=mt&-mu mhh< jj Jhh< jj 4^_̸$ |$,Vt$,= mjM mD$PQt$8 tF t PV9hh< jj mt.=mt%)mu mhh< jj Xhh< jj B^$̸$ D$<W|$0Vt$0u#D$@L$RF F N PQVsPhT +RD,0P&]D$4P@u~+YAu}++;эT}}+QWR }#+QWRD$( P@u+¹hP +QT$R\L$D$(PRvtD$PV:]$_^[3 ̋T$L$̸ W39= mu 9=mShh< jj mD$Pm9=mtL$QhltRhh< jj 9hh< jj &hh< jj %mT$8Rhl8mVhh< jj mt$4t$|$|$;t.L$Qh4PDD$$ ;tT$PRh VZ}hh< jj m5m=m;tP= mm;t!PMumPۍ=mh4h< jj 5mhh< jj ^mt-9=mt%)mu mhh< jj hh< jj [_̸ = mSSVhh< jj tmD$PV=mtL$Qhl{tRhh< jj !hh< jj hh< jj %mT$8Rhl8mhh< jj 'Phh< jj $mt.=mt%)mu mhh< jj shh< jj ]tD$PjjjVVV^[̋D$PQH RP@QL$RP҃̃= mt?hfh< jj mD$Ph7Q^hih< jj ,̋D$u Ãuht hd j$h4mX4mÃu"hP h@ hhXmWXmÃuh4 h$ jh mW mà t ̸?̡xouDhh jj =xou xohh jj xoVhh jj 395xouD$xohh jj ~^Vhh jj W=|ouh@h qL|ou3hh jj ^Vt$FhP!PMV ^̸ ֿ =|ou hu Wh0h jj \$ |oD$PQ臎uIVh4h j < t-~虇FVu |oR;^hEh jj BuhGh jAjijf_ SVhSh j uhVh jAjhj^ [ËD$ L$T$h^h D$ NL$$jj VFN WRv;G#GjPctCOQS;G~݋_GVSSPWg hkh jj A^[hch jAjhjdVVhuh jj hwh @jj  ^̃=|ou Rt3|oh9P |oQB |oxoS\$[uËL$T$WQL$RT$QL$RQ<_̃=xou?hh jj $=xou xohh jj xõ=xou?hh jj =xou xohh jj xoH̃=xou?hh jj d=xou xohh jj ;xoH̃=xou?hh jj =xou xohh jj xoH ̃=xou?hh jj =xou xohh jj {xoH̃=xou?hh jj D=xou xohh jj xoHW|$?u'uh]h jAjfj3_ËSVP襁\$;jQ莀tF;~T$RSP褁 ^[_hgh jAjfj賺^[3_Vt$u3^P+L$;}QP'^S\$W33؅u_[ËD$UVhh jj8KQր~Bhh R t"3~$CVP覀F;|hh jj~#uhh jAjlj踹^]_3[3~StGxtA\$tP+;|3 VQ' QRIRVSPD$,PуF;|t W^]_[̸ָ UVt$39.u^E]YS\$؅u[^]YWhh jjCPQw;}~@hh R# t 3~d$CVPFDF;|hh jj7~$u hh jAjjjW_[^3]Y3~r\$ tP~;|3 VQ~D$Dt!xtPRQL$$VT$RPSQ҃D$L$PVQF ;|t U_[^]YS\$W3s؅UVhh jjDCP~~;h h Q t3~SVR}F;|hh jj~!uhh jAjkj^]_[Ë\$3~QtCx t=tPw};|3 VPs} QRI RVSPD$,PуF;|t WtP|^]_[̡PŭuhP3hj'̋D$P uVWD$ _^VN򸫪*ʍI+io*‹9$Q@+t$9i0^́ k9SVWi:ȍqi⻷ڋi+ʍ=iҏ gfff‹T$+ȉ 颋.ϋkd‹T$ @+D$28_^[SUVW\$E.iQl$+؋t$FV+ȍ+ȍ؁Q| EQ }MÀQF ~NlAP|$ L$D$L$QT$RL$$QvD$( wdFD$HFų L$‰FN ʋ<G_V++ډ^][_^]3[% % ̋T$ L$3tVt$ +W<+uJAu_^SVt$ \$W= umhD u _^3[hDjP  PSX @@u0P _^3[Ë@PR\ tH,hQDP  _ƂC^D[ ^3[Vt$t,t&@PT Q ^ 3^;3+|$uj\h jejmj謱3̃=ou oUSVW1ҜX5 PX111GenuŁineI Łntel AuthƁenti ƁcAMD g=UƸ ́8F9￁@* ,1%== _^[]Ð11ҍ !1Ð !0X%!X 1RP1+$T$11ÐX 2D$L$ؐ1@;11Ð11ҍ  !F ffffffff㐍D$ÐT$L$S[ÐUM $UT$ED$ED$ ED$E D$E$D$U]ËT$L$1*RÐ IRIRÐ=D̸H |$TL$LD$PSYUiVq T$\WP@ P@ P@ @P@ P@ P@ PL$0@3͉|$P@L$d#38L$` x@ x@ ׉T$ 3#3T$0@x0@ x@ x@ t$@3#3@t$ 8h @h @h@ |$ @h3#3|$@@X h@ h@ ݉\$83#3\$@h@ h@ h@ ͉L$(3#3L$8@h@ h@ h@ @hT$H3#3T$(@p h@ h@ t$ @h3#3t$H@x h@ h@ |$43#3|$@h@ h@ h@ ݉\$$3#3\$4@h@ @( h @L$D3@h#3L$$@P h @h @T$ @h3#3T$D0 @h @h@ t$<3#3t$@h8@ h@ h@ 3#3l$<@|$,8X @X @X @|$L3#3|$,@ 3#3L$L#ً # T$Pٍ2yZ#ދ ։T$T# T$\$`*yZT$T# T$l$:yZ #Ջ# T$ߍ yZ ## T$0ٍ2yZ #މ\$`# l$8\$+yZ# T$`\$T$4:yZ # # |$<yZ #ˋ# L$ ߍ1yZ#ދ Ή\$`# l$(\$+yZ# L$`\$L$$yZ #Ӌ# T$,:yZ #Ӌ# T$@ߍ2yZ #ދ# l$H\$`\$+yZ# T$`T$D yZ #Ӌ# T$L:yZ 33T$P2n33T$n 33T$ n 3ы3l$/n3T$ 2n33t$$n 33t$(n 3͋3t$,>n3L$0n33T$4n 33T$8*n 3Ӌ3l$<.n3T$@ n33L$D9n 33L$Hn 33L$L1nL$\iy iq|$dYq T$`h_^][HËT$UW|$Vt$F ;sFFFXSNtjn@s" 8@sWRUk ~X[^_]û@+SR(RI jUVD$0j@ jUL$<+FX( l$<$vSUV| +tW~XUV [^_]̋D$L$jPQ? SVW|$_Xw3C8v @+PjS蛥 jVW38+QjS{ WV8G8FOFNWFVGFFOFNWFFGFj?VWj@jVGX D$4@@@OH@@@@O@@@у$@O H@@@_^H[̸\ Vt$luoD$P~u^\ËL$hT$dQRD$ PL$QVT$j\R^\̋T$UW|$Vt$F ;sFFFXSNtjn@s" 8@sWRUˣ ~X[^_]û@+SR(R詣 jUVbD$0j@ jUL$<+FX舣 l$<$vSUV, +tW~XUVN [^_]̋D$L$jPQ SVW|$_Xw3C8v @+PjS jVW38+QjSۢ WV8G8FOFNWFVGFFOFNWFFGFj?VWKj@jVGX~ D$4@@@OH@@@@O@@@у$@O H@@@_^H[Vt$j\jV #EgFFܺF vT2^̸\& Vt$luoD$Pu^\ËL$hT$dQRD$ PNL$QVCT$j\R'^\VW|$ t$L$US@Q_OW ϋ.1!ߍ(xj1n1!Ǎ*V1 n1!׍)p $1n 1!ύ+ν1n1!ߍ(|1n1!Ǎ**ƇG1 n1!׍)F01n1!ύ+F1n 1!ߍ(ؘi1n$1!Ǎ*D1 n(1!׍)[1n,1!ύ+\1n01!ߍ("k1n41!Ǎ*q1 n81!׍)Cy1n<1!ύ+!I1nˍ(b%1!׋n1؍*@@1!ϋn,1 )QZ^&1!ߋ.1э+Ƕ1!Njn1ˍ(]/1!׋n(1؍*SD1!ϋn<1 )1!ߋn1э+1!Njn$1ˍ(!1!׋n81؍*71!ϋn 1 ) 1!ߋn 1э+ZE1!Njn41ˍ(1!׋n1؍*1!ϋn1 )og1!ߋn01э+L*1!Njn111ߍ(B9n ߍ*q11Njn, 11׍)"amn8׍+ 811ϋn11ߍ(D꾤nߍ*K11Njn 11׍)`Kn(׍+p11ϋn411ߍ(~(.ߍ*'11Njn  11׍)0n׍+11ϋn$11ߍ(9n0ߍ*11Njn< 11׍)|n׍+eV11ϋ.1 ߍ(D")1ϋn1 Ǎ**C1ߋn8 1 ׍)#1Njn1 ύ+91׋n01 ߍ(Y[e1ϋn 1 Ǎ* 1ߋn( 1 ׍)}1Njn1 ύ+]1׋n 1 ߍ(O~o1ϋn<1 Ǎ*,1ߋn 1 ׍)C1Njn41 ύ+N1׋n1 ߍ(~S1ϋn,1 Ǎ*5:1ߋn 1 ׍)*1Njn$1 ύ+ӆ1׋l$@}}}} E]<$MU 9X[]_^̸T L$XD$\SYUVW9iq IL$H @H @H @T$TP@H @H @H @T$X@3#3΋T$T@ʋT$t$lyZH P@ P @L$$@3#׋L$X3ыL$l yZ@l$( ͉|$@( h @L$,@L$$3#3L$)yZh@ h@@ ( L$4L$t$3#3H@l$,@ P@ P@ ʍyZL$+@,h@0kA@4ك@8y!~@<[H@HDHHHLǀ@ASVt$W~P;Cpv +PjS8x jWV3)9p+QjSx V@WF@NDG~V@FDW}VDN@O|F@VD w G{F@VD(w GzFFGyNGOxVHWwFHNLGvVHFLWuVLNHOtFHVL xw GsFHVL(hw GrFNGqNOjWVOp>8D$ u_^3[Ë0c@uyUNV@X@@XX@وX@@@XV@N@@@و@X@X@@N@@@@X@وX@@@XV@N @@@و@@@@@ ]G_^[ËN@X@@XX@وX@@@XV@N @@@و@X@X@@VN@@@@X@وX@@@XV@N@X@X@Xو@@@PV @N$@@@@و@ڋ@@P@@N(v,@@@ֈP@P@@_^H[[̋D$UVt$ W|$nPD$NDǺS^@;wr;sFHVLF@VDtX+;sL$WQPAs [_^]ËT$SRP"s D$$jU+Vdž 4\$rQSV3߃ +߅tWSUr [_^] ̋D$L$jPQ3 ̸r l3ĉ$$V$uHpD$P$QRT$RD$PVL$hQ$ ^3q ̸vq l3ĉ$$V$upD$P$QRT$RD$PVHL$hQi$ ^35q USVW]57-V)%@ =P6Al$t$D$LD$h} ^NV ʉ$\$L$T$ F^NVʉD$\$L$T$F ^$N(V,ʉD$ \$$L$(T$,F0^4N8V<ʉD$0\$4L$8T$yZ|$ 3|$13|$,!3<$1|$ yZT$3T$13T$013T$T$ nL$3L$13L$413L$L$n\$3\$ 13\$813\$ \$nD$3D$$13D$<13D$D$0nt$ 3t$(134$13t$t$ >n|$$3|$,13|$13|$|$$nT$(3T$013T$13T$T$( nL$,3L$413L$ 13L$ L$,n\$03\$813\$13\$$\$0nD$43D$<13D$13D$(D$40nt$834$13t$13t$,t$8>n|$<3|$13|$13|$0|$<n$3T$13T$ 13T$4$ nL$3L$ 13L$$13L$8L$n\$3\$13\$(13\$<\$nD$ 3D$13D$,13$D$ 0nt$3t$13t$013t$t$>n|$3|$13|$413|$|$nT$3T$ 13T$813T$ T$ nL$3L$$13L$<13L$L$n\$ 3\$(13$!3\$\$ +ܼ!D$$3D$,13D$!3D$D$$(ܼ!t$(3t$013t$!3t$t$(.ܼ!Ջ|$,3|$413|$ !3|$ |$,/ܼ!͋T$03T$813T$!3T$$T$0*ܼ!݋L$43L$<13L$!3L$(L$4)ܼ!ŋ\$83$13\$!3\$,\$8+ܼ!D$<3D$13D$!3D$0D$<(ܼ!4$3t$13t$ !3t$44$.ܼ!Ջ|$3|$ 13|$$!3|$8|$/ܼ!͋T$3T$13T$(!3T$<T$*ܼ!݋L$ 3L$13L$,!3 $L$ )ܼ!ŋ\$3\$13\$0!3\$\$+ܼ!D$3D$13D$4!3D$D$(ܼ!t$3t$ 13t$8!3t$ t$.ܼ!Ջ|$3|$$13|$bʋ|$43|$<13|$13|$(|$4bʋT$83$13T$13T$,T$8 bʋL$<3L$13L$13L$0L$<bʋ$3\$13\$ 13\$4$bʋD$3D$ 13D$$13D$8D$0bʋt$3t$13t$(13t$<t$>bʋ|$ 3|$13|$,13<$|$ bʋT$3T$13T$013T$T$ bʋL$3L$13L$413L$L$bʋ\$3\$ 13\$813\$ \$bʋD$3D$$13D$<13D$D$0bʋt$ 3t$(134$13t$t$ >bʋ|$$3|$,13|$13|$|$$bʋT$(3T$013T$13T$T$( bʋL$,3L$413L$ 13L$ L$,bʋ\$03\$813\$13\$$\$0bʋD$43D$<13D$13D$(0bʋt$834$13t$13t$,>bʋ|$<3|$13|$13|$0bl$`T$d}uE] M}@u;T$hEω] ։ML_^[]ÐUSVW]fo}foEfoM foU0fou@|$l$T$fD$pf$f$f$f$@$$$$_OW oEoMoUo]f8f8f8f|$`f8ffff$ffL$ffT$ ffo <$1f:foffD$@!1fs1ffT$1ˉf!1f|$01fofoL$1fs f!1fr1fofrf\$ 1ljfrf!1foD$`1ffoD$1f:foffL$P!1fs1ff|$1щf!1f$1fofoT$1fs f!1fr1fofrfL$1؉frf!1foL$p1ffo\$ 1f:foʼnffT$`!1fs1ffD$$1f!1fL$1fofo|$(1fs f!1fr1fofrfT$,1foD$@frf!1foT$p1ffoL$01f:foΉff\$@!1fs1ff\$41ljf!1fT$ 1fofoD$81fs f!1fr1fofrf|$<1foL$Pfrf!1fo\$p1ffo$ff:1ˉffd$P!1fof1fL$1fof\$0!1fr1fr\$1ljf!1foT$`1D$ fo1!11|$ff:1։ffl$`1foffT$1͉fof$$1frL$1fr1f\$1fo\$@1foD$ ff:1fft$@1fo$ff|$$1Չfofl$1frT$(1fr1fL$,1fod$P1fo\$0ff:1Ɖff|$P1foffD$41foft$ 1fr|$81fr1fT$<1fol$`1fo $ff:1މffD$`1foff\$1ʼnfof|$01frD$1fr1f|$ 1fot$@1foT$ff:1ΉffL$@1foffL$1݉fof$1fr\$1fr1fD$1fo|$P1foff:1|$ !ffT$P!foff1fofL$1T$$!fr!fr1f1foD$`L$(!!foΉ1щ1\$,!!1ˉff:1D$0!ff\$`!fo$ff1fofT$ 1|$4!fr!fr1f1foL$@T$8!!fo׉11L$USVWt$|$D$]4$|$D$\$ _OW PSQRG_OWPSQRG _$O(W,PSQRG0_4O8W<PSQR@ |$d^N~ \$L$|$ V^N~\$L$|$\$\t$11|$1T$!֋T$ 1 \$1 t$1ڋ|$ˉ$ !!u ȁt$ދL$d 111 $1\$xt$1\$\1|$1T$!֋T$ 1 \$1 t$1ڋ|$ˉ$ !!u ȁ؋$xqN$`\$L$|$ ^N~ ^N~ D$\$L$$dVF^NVF^N`;|$d$ _^[]Ð/BD7q۵[V9Y?^[1$} Ut]rހܛtiGƝ̡ $o,-tJܩ\ڈvRQ>m1'Y GQcg)) '8!.m,M 8STs e jv.,r迢KfpK£Ql$օ5pjl7LwH'4 9JNOʜ[o.htocxxȄnjlPxqSHA256 block transform for x86, CRYPTOGAMS by USVWt$|$D$]i 4$|$D$\$ "ooNoVo^of on(ov0o~8PL$T$\$l$(t$0|$8WʉL$LT$H_ˉD$D\$@ol$(ot$0o|$8oosd$ sossss}oL$oT$od$$oo\$HssossssooÊUǁ5ol$(ot$0o|$8oosd$ sossss}oL$oT$od$$oo\$Hssossssoot$Xo$oÊUǁosososos ss*o$s8sԔ$ss*\$Hol$(ot$0o|$8oosd$ sossss}oL$oT$od$$oo\$Hssossssoot$Xo$oÊUǁoL$oT$o\$ol$(ot$0o|$8NV^f n(v0~8NV^f n(v0~8Ā;|$XHwd$\_^[]Ð_OW PSQRG_OWPSQRG _$O(W,PSQRG0_4O8W<PSQRG@_DOHWLPSQRGP_TOXW\PSQRG`_dOhWlPSQRGp_tOxW|PSQRǀH$|$󥐋L$(T$, 1111111111L$0T$4t$8|$<D$@\$D11#L$(#T$,$$11u}ӋL$ T$$$\$ӋL$T$ D$ \$$1111111111L$T$ t$|$$\$ #L$#T$#t$#|$ Ӊ$\$Um$8$<111111111$\$$$1 1 1 1 1 1 1 11$@$D$\$$$$$L$(T$, 1111111111L$0T$4t$8|$<D$@\$D11#L$(#T$,$$11u}ӋL$ T$$$\$ӋL$T$ D$ \$$1111111111L$T$ t$|$$\$ #L$#T$#t$#|$ Ӊ$\$Um$H$L^NV D$\$ ^L$T$NV F^NVD$\$F^L$ T$$NVF ^$N(V,D$(\$,F ^$L$0T$4N(V,F0^4N8V<D$8\$2-m1?!'Y= % GoQcpn g))/F '&&\8!.*Zm,M߳ 8ScTs ew< jvG.;5,rdL迢0BKfpK0TQlReU$* qW5ѻ2pjҸSAQl7LwH'Hᵼ4cZų 9ˊAJNscwOʜ[o.h]t`/CocxrxȄ9dnj(c#齂lPyƲ+SrxqƜa&>'!Ǹ}xnO}orgȢ}c ?G5 q}#w($@{2 ˾L*~e)Y:o_XGJDlSHA512 block transform for x86, CRYPTOGAMS by ̋D$@RRRRH H%%%%HH̸1 l3ĉ$$U$VbSHW} @D$FFNFV FFF NF VF NF Š D$D$ D$(E$@ W\$ \$(FE-L$0QW.jT$?Suj}h QZR 3FRPQ( [t_^VWjNh4 h R3 ;u_3^ÍFP>~ ~~FBD$x$p_^W|$Wu_ËD$ SVp_SVRS tF tNQPW- u^[3_^[_̋D$VpNQ?N t$Ft PQyV RRF VR^̋D$@x u3ÃP-tL$PhWQ` ̋D$HAT$ L$RQPC ̋L$QVt$ F%PRhV7F^̋L$D$WxQ^P}3_Vt$D$tT$ RPW u^_ËD$ ^_̋D$T$Jt_t0tËBR@RR@RPQSu1ËT$D$ u|PRQK u 3ËT$W|$u3_Vt$X ƍ$:utP:Quu3uD$ @jWP ^_ùP Ɛ:utP:Quu3u[L$QW^_ùl ƍd$:utP:Quu3u/W!tgL$ QIQPjjR^_ùP Ɛ:utP:Quu3u^T$RWgu^3_ËL$D$ @|jjQVPcuV3G^_VG^_^_̋T$UW|$Vt$F ;sFFF\SNtjn@s" 8@sWRUK ~\[^_]û@+SR(R) jUVbD$0j@ jUL$<+F\ l$<$vSUV, +tW~\UV [^_]̋D$L$jPQ SVW|$_\w3C8v @+PjS{ jVW38+QjS[ WV8G8FOFNWFVGFFOFNWFFGFj?VWKj@jVG\ D$4@@@OH@@@@O@@@у$@O H@@@@OH@@@_^H[̸` Vt$pupD$PNu^`ËL$lT$hQRD$ PnL$QVcT$j`Rk^`̋T$D$V WrUzSlh$l$Xh \$l$ Xh\$l$Xh\$l$X h$\$ l$$X(h,\$(l$,X0h4\$0l$4X8h<\$8l$pm) T$ 1Ⱥ >pm)D$ 1 >pm)΋T$ 1غ >pm) D$ 1 >pm)݋T$8 1 >pm)D$ 1ʸ >pm)T$$ 1 >pm)΋D$, 1ڸ >pm) T$ 1 >pm) ݋D$0 1 >pm)T$ 1Ⱥ >pm)D$( 1 >pm) ΋$ 1غ >pm) D$ 1 >pm)݋T$4 1T$ >pm׉)!! ‹D$ vmzƉ)!! ЋT$ vmzщ)!! ‹D$ vmzʼn)!! ЋT$ vmz Ӊ)!! ‹D$, vmzlj)!! ЋT$< vmz։)!! ‹$ vmz)!! ЋT$ vmzՉ)!! ‹D$0 vmzÉ)!! ЋT$ vmz ׉)!! ‹D$4 vmz Ɖ)!! ЋT$$ vmz щ)!! ‹D$ vmz ʼn)!! ЋT$( vmzӉ)!! ‹D$8 vmzlj)!! ‰ vmz1T$01 Ɖ1؋T$<1 1T$(1 ʼn 1T$1É 1 T$1 lj 1T$1Ɖ 1΋T$ 1 1T$1ʼn 1݋T$1 É1ȋT$1lj 1 T$41 Ɖ1؋T$81 1$1 ʼn1T$ 1É 1 T$$1 lj 1T$,1 ֋$ ΋BËD$HËBŋD$LŋB D$PBƋD$@ƋNjD$DNj$jJ-r z%$ϋ$@$+l[]_^̸p̋D$ H HP HP HP HP HP HP P̋T$3V$: u Ar^3^SVW|$ 3+׹ǃr;uF|_^3[_^[̸& T$ SUVrFFF VFF VW~ V ~6  ׋333֋3̋333ϋ33׋3UUUU33֋D$333΋3UUUU33֋   ,( T$zt  ʁ  ϋ (# T$ ("   (! փ? ( T$ Ӂ ('  (% ? (& ? ($  8 L$9t  t$ \$ʁ  ΋ (# T$߁ ("   (! ׃? ( T$݁ Ձ ڋ('  (% ? (& ? ($  0 L$yt  |$ l$݁ʁ  ϋ (# T$ ("   (! փ? ( T$ Ӂ ('  (% ? (& ? ($  8 L$yt΋  t$ \$΋ցف ف Ӌށ(#  (" ف  (! ? (  4('   4(% ? 4(& ߃? 4($ ڋ  ։T$l( T$@_^][YVt$Vu^Vt^ËD$ PV3^̃=pt=Vt$V\u^Vzt^ËD$ PV3^ËL$T$QR3̃=$t2h( h( h( h( h( j hq"$q̸f D$ P@ P@ P@ @P $@ P@  ыL$T$T$QRD$PF8L$ D$@@@L$@@@H̸ |$$D$ SUVWH@ H@ H\$(@ht$$|$ @ H@ H@  CD$(؍ ÉL$0OG OG OG OG_G _G _G3‹T$,j ˉD$RD$3PGL$$7D$ FFFD$$FFFF Fl$(R\$0|33wL$OOGO GO GO GO_O _O  3͉L$L$,3jQT$RD$ E6D$ FFFD$$FFȃ F_F^][ H@P@ H|$$t$ @h@ P@ H@ D$(  \$4l$D$0HL$(ٍȉD$0.NFVFFF^F NF VF FF ًL$, jQT$ Rl$ F\$$-5D$@3D$ L$3L$$GGGGGGG Gl$(l$4\$JD$0݋l$NFV FNF FVD$FNF   ȋD$,jL$PL$Qh4D$<3l$$3\$ | ̓w=$OOOOOOO__^][ Ë|ukaY̸v D$ P@ P@ P@ P@@V0L$H@  ʃ|$$L$^tL$T$D$QRPL$ Q4T$D$L$RPQT$ R5L$D$ @@@L$@@@H̸ |$$D$ SUl$V0W|$,M_ P@ P@ @PL$@ P@  ыL$(jT$QT$RJ2L$È@@L$ @@@ HL$2>AL$L$ >FAL$ 5D$0_0^][Å|$,M_ P@ P@ @PL$@ P@  ыL$(jT$QT$Re1L$È@@L$ @@@ HL$AL$ >>2L$ FAL$ 3D$0_0^][ø |$,D$(L$SUV0W|$4IL$4_ P@ P@ P@h@L$H@ ȋD$( ʋT$,L$L$0QRPL$Q1L$ È@@L$$H@@@HL$4>T$2BT$T$ >FBT$ #D$8_0^][Å|$4IL$4_ P@ P@ P@h@L$H@ ȋD$( ʋT$,L$L$0QRPL$Q0L$ È@@L$$H@@@HL$4T$BT$>>2‹T$ FBT$ !D$8_0^][̸@ l3ĉD$T$\$?T$@\$AT$CT$EЈD$DD$GT$FD$ID$\\$BшL$H؁T$JL$KyKCT<QRD$DP   T$=d$<*Êd$=T$<T$>d$>T$=T$?d$?T$>T$@d$@T$?T$Ad$AT$@T$Bd$BT$AT$Cˊ\$DT$BT$C ӈT$CD$=\$<L$>T$? D$@ L$A T$C L$B  ‰D$D$9l$V9l$`$T$,L$0)l$RD$(D$,PQT$,R\$0,33UL$D$w_$ FND$FN VN FN ȉL$FND$VN VN VN ‰D$T$\ u \$D$@u ؉L$T$=\$T$\$?T$@\$AT$CT$EЈD$DD$GT$FD$ID$\\$BшL$H؁T$JL$KyKCT<QRD$DP   T$=d$<*Êd$=T$<T$>d$>T$=T$?d$?T$>T$@d$@T$?T$Ad$AT$@T$Bd$BT$AT$Cˊ\$DT$BT$C ӈT$CD$=\$<L$>T$? D$@ L$A T$C L$B ыL$ ‰D$D$3D$ 3L$$Uw=$,OOOOOOOOD$9l$0T$8t$4FFFFFF[L$H_^]3) @ÐlbXPI?5-B 8 . "     m e ] U R J B : ̸0f L$<$AUVt$H%t$yH@ID$ ?gD$PH@PSXD$ @ H@ @P @ P@  ʃ|$XW\$L$PO;|$Ht$D)l$L$,L$TjQT$0R\$4&U 33wM$NNFN VN FN FNVN VN VN 3D$(3L$,Uw=$0OOOOOOOOT$L u L$PD$P?@u D$L$P1T$PL$l$D$L$T$ L$8T$D$?D<8\$H2l$$D$HGEE|$l$$d|$tNt$,FFVFFL$FV9_^][L$03 4ËT$:_^][L$03j 4ËD$L$@8_^][3Q 4̸(UV339-0qu#jmh( h@ 0q;u^]9- qujrh( h@v q;tա$q;ujwh( h@P $q;tSW=,q;t`t$;}* (qT$WQR _[^-,q-(q]Ë(qL$VPQ +=,q_(q[^]ÿ@9|$~|$\$I q+RPS  u 8t _[^3];~|ċ qQ1A P@@ ;z}F‹3~<+RQS  u 8r h; q|ċ|$;j}h(tD$(T$$P$qRVPQ( T$(D$$R$qPVRQ.$qL$0WPQX +5,q=(q_[^];}Y(tT$(D$$R0qPVRQ D$(T$$P0qRVPQ 0qT$0VQR _[^](t D$(T$$PD$ RVPQd _[^]ËT$(D$$RT$ PVRQd_[^]_[^]̸ l3ĉD$D$,S\$(Ul$0VD$ 4q3W|$0l$;u3jeh) h@ 4q;u_^][L$3 95,t5,@~]t$~>l$,+=@~@L$T$QRP7PUJD$;|ƋD$_^][L$3b Ë@@X}*St$ WR +PL,QoC‹t ;|ËT$jRUP4qPV |ËL$4qjQUPRV3~8l$, 4q+PQU  u 83;|̋ËL$$_^][3[ ̸( l3ĉD$$D$8L$4SD$D$DD$UV0W|$LWL$ ʍGPD$(@@ @X @l$@@ X ؋ ӈD$-وL$,D$.L$/ʋ‰T$ T$0|$DD$\$L$1D$2T$3L$u\L$$jQT$$Ro\$(D$9D$,L$:T$;ȋЈD$< D$\$,L$1T$2D$3L4,D$<2FM@E|$D$<z|$tRD$(@L$ @H@@@HD$_0^][L$$3 (ËL$_1^][L$$3 (ËT$L$4_2^][3k (̸ & Ul$0E@D$D$4D$o ~#@D$ |D$3MHD$"u D$ HD$ D$T$Rl$hD$$L$(1!!ʉ11ʋ]1؋M111%1ہ1ɈÈl$3|3 33 %1ߋ 1ߋ1ߋ1ߋl$ D$$L$(1!!ʉ11ʋ]1؋M 111%1ہ1ɈÈl$3t3 33 %1ދ 1ދ1ދ1ދl$ D$$L$(1!!ʉ11ʋ]1؋M111%1ہ1ɈÈl$3|3 33 %1ߋ 1ߋ1ߋ1ߋl$ D$$L$(1!!ʉ11ʋ]1؋M111%1ہ1ɈÈl$3t3 33 %1ދ 1ދ1ދ1ދl$ D$$L$(1!!ʉ11ʋ] 1؋M$111%1ہ1ɈÈl$3|3 33 %1ߋ 1ߋ1ߋ1ߋl$ D$$L$(1!!ʉ11ʋ](1؋M,111%1ہ1ɈÈl$3t3 33 %1ދ 1ދ1ދ1ދl$ D$$L$(1!!ʉ11ʋ]01؋M4111%1ہ1ɈÈl$3|3 33 %1ߋ 1ߋ1ߋ1ߋl$ D$$L$(1!!ʉ11ʋ]81؋M<111%1ہ1ɈÈl$3t3 33 %1ދ 1ދ1ދ1ދl$ D$$L$(1!!ʉ11ʋ]@1؋MD111%1ہ1ɈÈl$3|3 33 %1ߋ 1ߋ1ߋ1ߋl$ D$$L$(1!!ʉ11ʋ]H1؋ML111%1ہ1ɈÈl$3t3 33 %1ދ 1ދ1ދ1ދl$ D$$L$(1!!ʉ11ʋ]P1؋MT111%1ہ1ɈÈl$3|3 33 %1ߋ 1ߋ1ߋ1ߋl$ D$$L$(1!!ʉ11ʋ]X1؋M\111%1ہ1ɈÈl$3t3 33 %1ދ 1ދ1ދ1ދl$ D$$L$(1!!ʉ11ʋ]`1؋Md111%1ہ1ɈÈl$3|3 33 %1ߋ 1ߋ1ߋ1ߋl$ D$$L$(1!!ʉ11ʋ]h1؋Ml111%1ہ1ɈÈl$3t3 33 %1ދ 1ދ1ދ1ދl$ D$$L$(1!!ʉ11ʋ]p1؋Mt111%1ہ1ɈÈl$3|3 33 %1ߋ 1ߋ1ߋ1ߋl$ D$$L$(1!!ʉ11ʋ]x1؋M|111%1ہ1ɈÈl$3t3 33 %1ދ 1ދ1ދ1ދl$ $KƉ$T$ω1檪111%11 13333111ǁ11 1Ɓ11z_^[]̸覨 l3ĉ$$U$VuAEW) AuA$ȈE) 3ɊBt Ars+R jP茨 D$P$QäVWT$$RD$ PbD$$ȋЈ$$D$($$ȋ$$$$Ƅ$$_2҄tuA҄tuA҄tuA҄tuA҄tuA҄tuAҊ) .F r$^E ]3 ĘËD$L$h8qPQ ̸趦 SUVWD$DP@ P@ P@ @P@L$H P@ ЋD$H P@L$H P@ P@@ @0 p@  փ|$LL$HT$JL$@Q  JT$B JBl$8|$0Br  B rB  ΃t$4UT$DڍTT$8_G _G _G _GoG oG oG 3ЋD$<3T$33\$jPL$,QGT$0\$4oD$03D$TFFFVL$43L$FFFFF Fl$D@l$8|/33҃wL$tX_OWO WO WO WOoO oO  3ЋD$<3T$33\$jPL$,QT$0\$4D$03D$TFFFL$43L$FFFFу VT$@t$FFFFF_N^][ËD$@P@D$ P@@ |$4@p @ p@ D$8 ֋t$0T$DD$8PBT$ ڍЉT$8$.FFV FFF FFF3T$$VF NF ‹T$< D$L3D$jD$,RD$,PFL$P3L$43D$03L$$3D$ GGGGOGGD$XGGL$T Gl$ ݉D$D1ЋD$8.VFF FVF  3D$$FFNFV NF  ‹T$AL$L$ >FAL$ 7D$0_0^][Å|$,M_ P@ P@ @PL$@ P@  ыL$(T$QT$R L$È@@L$@@@HL$AL$ >>2L$ FAL$ 5D$0_0^][̸(薊 l3ĉD$$D$8L$4SD$D$DD$UV0W|$LWL$ ʍGPD$(@@ @X @l$@@ X ؋ ӈD$-وL$,D$.L$/ʋ‰T$ T$0|$DD$\$L$1D$2T$3L$uZL$$QT$ R\$$D$5D$(L$6T$7ȋЈD$8D$\$,L$1T$2D$3L4,D$<2FM@E|$D$k̸覃 D$SU(VpD$W8ыt+ы+hX+ыHΉT$t++ +8+p3ʁхt+ы++ыH3΅t+΋++33Ջh3L$3ځхt+͋+ʉL$ ++щT$pXPω\$t++ ++x3L$ׁхt+ы++ыH3υt+ϋ \$++ϋx33֋3L$3ځхt+ϋ+ʉL$ ++щT$pXP͉\$t+ڋ+ ++݋L$3L$xхt+ы+׋h+ы3υt+ϋ++ϋx33֋3L$3t$хt+ϋ+ʉL$ ++щT$phPˉl$t++ ++L$3L$xхt+ы+׋X+ы3υt+ϋ++ϋx33֋3L$3t$ځхt+ϋ+ʉL$ ++щT$pXP͉\$t+ڋ+ ++݋L$3L$xхt+ы+׋h+ы3υt+ϋ++ϋx33֋3L$3t$хt+ϋ+ʉL$ ++щT$phPˉl$t++ ++L$3L$xхt+ы+׋X+ы3υt+ϋ++ϋx33֋3L$3t$ځхt+ϋ+ʉL$ ++щT$pXP͉\$t+ڋ+ ++݋L$3L$xхt+ы+׋h+ы3υt+ϋ++ϋx33֋3L$3t$хt+ϋ+ʉL$ ++щT$phPˉl$t++ ++X3L$Ӂхt+ы++ыH3ރځ˅t+ˋ l$++ˋX33֋3L$T$3t++ ++X\$H΅t+Ћ+ ++׋D$ _҉0^ ]H[Y̸F{ |$(SUl$,VW%UEEMEE\$, E ыt$(|$$EM EE MEE M D$8CD$,؍ÉD$OG OG OG OG_G _G _G3‹T$0 3L$8D$RD$PGL$$T$ FNFFD$$FNFFFFFl$,D$8K\$|3D$,wV$OOL$,OO L$,OO L$,OO L$,OO_O _O  3ʋT$0L$L$,3RD$PL$$T$ FND$$FFFFFȃFMEMEMEU>]EEMEU|$(t$$EE E MEE U ME L$,\$D$8l$4L$AD$,؍T$.FFNFVF^F FF NF V ؋D$0F PL$ Ql$ F\$$D$3D$ L$@3L$$GGGGGGGGGl$,l$\$8Gl$4\$D$8L$NFVF NF D$D$FFVFNF V D$,D$D$0PL$QL$D$@3\$ 3D$$|w9$8OOOOOOO_L$T$,L$T$8ً‹MEUEME]EUEME_U^E][Ë& ̸Vv |$$D$ SUl$V0W|$,M_ P@ P @@PL$@ P@@ ыL$(T$QT$RL$È@HL$@@@@уHL$2>AL$L$ >FAL$ 1D$0_0^][Å|$,$M_ P@ P @@PL$@ P@@ ыL$(T$QT$R+L$È@HL$@@@@уHL$AL$ >>2L$ FAL$ /D$0_0^][̸(Vt l3ĉD$$D$8L$4D$D$@D$SUV0W|$LWL$GD$(@@ P@X@ P P@ @ ؋l$@D$,D$- ӋD$.D$0D$1|$DD$L$T$ L$/D$2T$3\$AL$L$ >FAL$ 1D$0_0^][Å|$,$M_ P@ P @@PL$@ P@@ ыL$(T$QT$RL$È@HL$@@@@уHL$AL$ >>2L$ FAL$ /D$0_0^][̸(6` l3ĉD$$D$8L$4D$D$@D$SUV0W|$LWL$GD$(@@ P@X@ P P@ @ ؋l$@D$,D$- ӋD$.D$0D$1|$DD$L$T$ L$/D$2T$3\$ |$$D$ SUl$V0W|$,M_ P@ P @@PL$@ P@@ ыL$(T$QT$RL$È@HL$@@@@уHL$2>AL$L$ >FAL$ 1D$0_0^][Å|$,$M_ P@ P @@PL$@ P@@ ыL$(T$QT$RL$È@HL$@@@@уHL$AL$ >>2L$ FAL$ /D$0_0^][̸(6< l3ĉD$$D$8L$4D$D$@D$SUV0W|$LWL$GD$(@@ P@X@ P P@ @ ؋l$@D$,D$- ӋD$.D$0D$1|$DD$L$T$ L$/D$2T$3\$>^//q^//qSSSShh,,@ `@ `yyȶ[[[[jjjjFFggr99Kr99KJJޔJJޘLLԘLL԰XXXXJJkk**OOCCņCCŚMMךMMf33Uf33UEEϊEEPPPPx<!>!KKݖKKaa pppp|>>B|>>BqqffffHHؐHHaaaaj55_j55_WWWWiiXX:':'''88++"3"3iiiipp33--<"<" IIUUUUP((xP((xzzYY   ee11BBƄBBhhhhAAÂAA))Z--wZ--w{{˨TTTTmm,:,:c|w{ko0g+׫vʂ}YGԢr&6?4q1#'u ,nZR;ֳ)/S [j˾9JLXCM3EPfHa5WiَU(ߌ BhA-Tc|w{ko0g+׫vʂ}YGԢr&6?4q1#'u ,nZR;ֳ)/S [j˾9JLXCM3EPfHa5WiَU(ߌ BhA-Tc|w{ko0g+׫vʂ}YGԢr&6?4q1#'u ,nZR;ֳ)/S [j˾9JLXCM3EPfHa5WiَU(ߌ BhA-Tc|w{ko0g+׫vʂ}YGԢr&6?4q1#'u ,nZR;ֳ)/S [j˾9JLXCM3EPfHa5WiَU(ߌ BhA-T @6USVWt$|$$_)ہ)܁D$]$) +oofd$t$fw_^[]Ðl$^NV \d$t$^NV _^[]Ð|$33_3O3W t64t$}u}u}u }@u`Ɓt5|=1|=1|=1t$ށt5|=1|=1|=1t$΁t5|=1|=1|=1TL 1ʉ\1D1‰΁怀 )%1Ɖ怀)11މ怀,)111111111ًD$1L$ ց怀)1މ怀 )11Ή怀, )111111111ʋ\$1T$Ɓ怀 )1Ή怀 )11։怀,)1111111111ށ怀 )1Ή怀 )11։怀,)111111111ӋL$ 1T$|$l$33_3O3W ;|$|$Ɓt5|=1|=1|=1t$ށt5|=1|=1|=1t$΁t5|=1|=1|=1|$TL 1ʉ\1ڋ\$D1‹D$3G3_3O3WÐgt64t$D$D$ E]MUE] M@U`p ~p L5~Tpt5 t5 pt5 t5 n~L5~t5 t5 t5 nT5t5 bt5 \ t5 nD nb;|$wooppoopprrrrrrrro\$ddoooorrrroT$ddpٱpddoopѱprrrroowErr]rrMU@gÐ|$33_3O3W t64t$Ɓt3t3t3tt$ށt3t3t3tt$΁t3t3t3t|$T3T3T\$3TD$33_3O3W ;|$|$%}u}u}u }@u`mƁt5|=1|=1|=1t$ށt5|=1|=1|=1t$΁t5|=1|=1|=1|$TL 1ʉ\1ڋ\$D1‹D$33_3O3W ÐQPQP~AeS~AeS:'^:'^;k;kEEXXKK 0U 0UvmvmvvL%L%OO**&5D&5DbbޱZIޱZI%g%gEE]]/u/uLLFFkk__mzmzRYڕRYԾ-Ծ-Xt!Xt!Ii)Ii)DDu‰ju‰jyxyxX>kX>k'q'qݾOO f f}:}:cJcJ11Q3`Q3`bSEbSEdwdwkk++pHhXpHhXEEllR{R{s#s#rKrKWWfU*fU*((//{{770(0(##jj\\++yyNiNiee4b4bĦĦ4.S4.SUU22uu 9 9@`@`^q^qnQnQ>!>!==>>MFMFTTq]q]oo`P`P$$ֽֽ闉@C̉@CgٞwgٞwBB[8[8yyۡ| G| G|B|B 2+H2+HpplZrNlZrN8V8V==6-9'6-9' d dh\!h\![Tћ[T$6.:$6.: g gWWҴOOa a ZwKiZwKi⓺ ⓺ **<"C<"C  ǭǭ--WWuLuLݻݻ``&&\r\rDf;Df;[~4[~4C)vC)v##ܶhhcc11BcBc"@"@  J$}J$}һ=һ=22)m)m/K/Kܲ0ܲ0 R Rww+l+lppHHGd"Gd"ĨĠ??V},V},"3"3INLJIN88ʢʢ 6 6Ϧϥz(z(ڷ&ڷ&??,:,:Px Px j_̛j_̛T~FbT~Fbظظ.9^.9^ïï]]iГ|iГ|o-o-%%Ȭ;Ȭ;}}cncn;{;{&x &x nYnY욷욷OOnene~~!!ٺJo6Jo6 )|)|11*?#1*?#1ƥ0ƥ05f5ftN7tN7ʦʦаа33JJAAPP//vM֍vM֍CMCM̪MT̪MTߞѵѵLjLj,,FeQFeQ^^5]5]tsts A. A.gZgZRRV3V3mGmGaa7 z7 zYY<<Ω'Ω'a5a5zGh>8$4,8$4,£@_£@_rr% % (Ky xZݨ31Y'_`QJ -zɜ;M*Ky xZݨ31Y'_`QJ -zɜ;M*Ky xZݨ31Y'_`QJ -zɜ;M*Ky xZݨ31Y'_`QJ -zɜ;M*t$ |$$_OW L$(vt$ WT$$L$('t$0OW ^NV d$_^[]Üw׻)9 <1|$0֋_D$(8d$4oof|$,t$ D$<\$$L$(|$0oongo/c[\$$vt$ L$(wd$_^[]Ü`w߉Ɛd$_^[]Ü^NV |$<_OW |$,}|$0t$(33_3O3W ^t$(t$$^NV vt$$t$<^NV _OW t$ vt$ yd$_^[]Üt$<^NV t$ ^NV _OW L$(|$$t$̀       p*Zx"RM|1}0L>PˏᛱD*nzߥ#6. ;$q Ɠz/U^) @iJ#cǽomxzj_t5+Aѐ                                    }|M*p[[[[[[[[[[[[[[[[`)Ih!APQ \] G@]Ziܵ6_wA(G]Z@6wA(i_POLSJ[Ȃ4~o%ՆPOLS{O1 j^~o[%4J3'bQvE鬟_T [PENAJe`㆔rwֆSLOPI;e,^rW}9D*n$< 1)Bd"F&`gYͦkU2> &Fd`B"ͦU 2>Ykg@~S->ԹmDVYKVector Permutation AES for x86/SSSE3, Mike Hamburg (Stanford University),$fo}fouÐfofoUfo*frff8foEf8ffxfoe f8ffoE0f8ffom@f8foL foUPf8ffo$ fof8ff8܁ff80f-foffrffomf8ffof8ffof8ffof8ffoo*f8f.foe`foEpf8ff8foL @ff8Ð`fofoSfȉfro*ff8foCЁ0f80ffof focf8ffoCf8fāf8fo#f8ffoCf8f-f8foc f8ffoC0f8ff8foc@f8ffoCPf8ff: foffrffoUf8ffof8ffof8ffof8ffof8fofoc`f8ffoCpfof8ff8Ð,$ofo@fo؍]fT$Ofo fo f80=w! 7H+oFfoff:H`oFfoH,fpf|$fofo|$fo f8` fPfffffffffpƀffpffofÐfoT$ff:f:ffpf:fT$fofsffofsffPfoefomfoffrffoUf8ffof8ffof8ffof8ffof8ffoe f8foE0f8fffoÐfoUfoffrffof8foCf8fÐfofo<fPf8fof8ff8ffoUfoffrffof8fo^f8ff8foV f8ffo^0f8ff8foV@f8ffo^Pf8ff8foV`f8ffo^pf8fځfo f8ف0ÐUSVWt$\$ȋD$T$܉\$00- d$01_^[]ÐUSVWt$\$ȋD$T$܉\$0T -Xd$01_^[]ÐUSVW-1t$\$ȋ|$T$܉\$0old$0_^[]ÐUSVW-1t$\$ȋ|$T$܉\$0old$0_^[]ÐUSVWt$|$D$T$ -\$ȋl$$L$(oM)\$0<$T$l$Ǎ-JN of$T$fo3vKofL$fD$ $T$fD$foL$ 3v\$d$0 _^[]̋D$T$ D$JR Wf8I Rf8ÐD$T$ D$JR Wf8I Rf8ÐJR Wfff8f8If8Jf8f8؍R f8f8f8f8f8f8f8ÐJR Wfff8f8If8Jf8f8؍R f8f8f8f8f8f8f8ÐJR Wffff8f8If8f8Jf8f8؍R f8f8f8f8f8f8f8f8f8f8JR Wffff8f8If8f8Jf8f8؍R f8f8f8f8f8f8f8f8f8f8JR Wff8ff8fIf8ff8ff8f8&f8f8If8f8f8f8Jf8f8؍R f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8ÐJR Wff8ff8fIf8ff8ff8f8&f8f8If8f8f8f8Jf8f8؍R f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8ÐUSVWt$|$D$T$ \$$%AՉ=`oo^of on0ov@o~Pv`-`@o_o^g of o0on0w@ov@P`o~Pv`-`_g o0w@P``= O^uf =@n0v@W _g o0w@,JR Wf8I Rf8W__g _g o0Չ=`oo^of on0ov@o~Pv`-`Ao_o^g of o0on0w@ov@P`o~Pv`-`_g o0w@P``= O^uf =@n0v@W`_g o0w@JR Wf8I Rf8XW_@_g k_g o0_^[]ÐUSVWt$|$D$T$ \$$L$(<l$0o;o$ D$ D$D$ 1\$l$l$l$*fo,$fo׉f8E6WMWƍU Wf8If8Jf8ЍR f8f8f8f|$f8f8HvWfo7f8d$0|$(_^[]ÐUSVWt$|$D$T$ \$$L$(<l$0o;o$ D$ D$D$ 1\$l$l$l$fo,$fo׉Չf8JR Wf8I Rf86f|$vWfo׉7f8-qEMWU WWf8If8Jf8ЍR f86f|$f8f8ٍvf8f8~JWR Wf8I Rf8ًd$0|$(_^[]ÐUSVWt$|$D$T$ \$$Xl$P={o;$ D$ D$D$ 1L$L$L$l$f:f:"fffo$f:"kf:"Cf:"Ef:"Cf:"Ef:"fL$0f8fD$@f8fpfpـ=;f|$ Չ-fp@foL$ fpffpffp@ffffEMU Ifff8ff8ff8ff8ff8f8$FWN WfoD$WfoL$0_g ffD$@fo$^0f@W^Pv`fL$0f8Wo0WfD$@f8w@fpP`fpـ-ZL fo|$ f=fp@ffpf=fpffFWN WF0WN@WW_g o0w@JR Wf8I Rf86W7[.vWW_a;.vW~ WW_g 66~N WF0WW_Wg o0d$P_^[]ÐUSVWT$$t$(JR Wf8I Rf8ыt$|$D$T$ xD$`D$dD$hD$lD$pl$tfoffo\$`ff%Չ-` fpff $ffffffpffL$ffffffpffL$ ffffffpffL$0ffffffpfL$@fEffo^Wof fon0fov@foNPfv`f$f|$PfMU f\$f8fd$ f8fl$0If8ft$@f8ff8f8?foL$PfW$ffW\$Wd$ _Wl$0g Wt$@o0Ww@fpP`fo\$`ffffff-`pL `=fo= fpffffff/fpffofffff=@Gfpffoffffff,$ft$Yf|$ fpfL$0fffoo^of f$on0f\$ov@fd$ vPfl$0f|$@fk(L$@W$W\$Wd$ Wl$0_Wg o0w@PEvWJR Wf8I Rf8Wfo(^v WWWWW_ fo(^f v0WWWWWW_g 0fo(^f W$n0v@W\$WWGW$W\$WW_g o0@fo-D$p%foD$p2D$pf%rffD$pfpffl$`fWvO-+|$pWWJR Wf8I Rf8WWd$t_^[]ÐUSVWT$$t$(JR Wf8I Rf8ыt$|$D$T$ x1۩)D$`D$dD$hD$lD$pl$tՉfoffo\$`ff%-` fpff $ffffffpffL$ffffffpffL$ ffffffpffL$0ffffffpfL$@fEffo^Wof fon0fov@foNPfv`f$f|$PfMU f\$f8fd$ f8fl$0If8ft$@f8ff8f8foL$PfW$ffW\$Wd$ _Wl$0g Wt$@o0Ww@fpP`fo\$`ffffff-`pL `=fo= fpffffff/fpffofffff=@Gfpffoffffff,$ft$Yf|$ fpfL$0fffoo^of f$on0f\$ov@fd$ vPfl$0f|$@f(L$@W$W\$Wd$ Wl$0_Wg o0w@PEvWJR Wf8I Rf8Wfo(^v WWWW_ fo(^f v0WWWWWW_g 0fo(^f W$n0v@W\$WWgW$W\$WW_g o0@fo-D$p%D$pBD$pf%ffD$pfpffo\$`ffffffpfofffWJR Wf8I Rf8WNvW-+|$pWJR Wf8I Rf8Wd$t_^[]ÐUSVWt$|$D$T$ l$$|$(}Չ\$(=g->vJWR Wf8I Rf8щى-(|)1ى=P)<$-P)$?oo^of on0ov@o~PDFW$WN WF0WN@WFPW_v`g o0w@P-`((Pt(=^(= f =0n0=@v@)<$WFW$WN WF0W~@W_g o0@(-PJR Wf8I Rf8W(-WWW(Ӎ(- o{WWW(_ ~ -0:;NF W~0WW_Wg 0(-@%)$)d$l$$}_^[]ÐWRw Bf:rf:af:Vf:Kf:@f: 5f:@*f:Ȁf:f:6 JP1RWWWÐ~P Bf:gf:f:Af:f:+f: pf:@f:ʀZJ01ÐR(foWfsWfpUfffpfÐ(D*NZR P RBRf:f:f:{f:f:ef:zf:Of:df:9f:Nf: #f: 8f:@ J1ÐRWWWÐRWWɪWøÐÐD$L$T$ /ÐD$L$T$ T$ ID  R@f8f8ɍR@@J9f81AES for Intel AES-NI, CRYPTOGAMS by ̃|$D$ L$T$PQRu % l ̋D$L$T$h3PD$QL$RT$PQR(d̋D$L$T$h3PD$QL$RT$PD$QRP_ ̋D$L$T$h3PD$QL$RT$PD$QRPb ̋D$L$T$h3PD$QL$RT$PD$QRP#c ̋D$L$T$h3PD$QL$RT$PD$QRPR KUSVWD$t$|$O)ف)́\$D$]^NȋV d$ȋt$ ʉ^NV _^[]Ð+D$D$TUSVWt$|$O)ف)́\$D$]^NȋV )d$ȋt$ʉ^NV _^[]Ð33_3O3W wD$\$L$ T$13_3TL3T3L3D$13\$ 13w1ʉT$1ىL$ 13W3\D3\3D3L$13T$13w 1É\$1ЉD$13_$3TL3T3L3D$13\$ 13w(1ʉT$1ىL$ 13W,3\D3\3D3L$13T$13w01É\$1ЉD$13_43TL3T3L3D$13\$ 13w81ʉT$1ىL$ 13W<3\D3\3D3L$13T$13w@1É\$1ЉD$@;|$:!ƋT$Ɖ1 O \$3L$ wL$ #O1D$1ʋwT$)ڋD$ \$13_3O3W USVWD$t$|$O)ف)́|$<\$]j^NȋV d$ȋt$ ʉ^NV _^[]Ð+D$D$TUSVWt$|$O)ف)́|$<\$] ^NȋV )d$ȋt$ʉ^NV _^[]Ð33_3O3W wD$\$L$ T$13_3TL3T3L3D$13\$ 13w1ʉT$1ىL$ 13W3\D3\3D3L$13T$13w1É\$1ЉD$13_3TL3T3L3D$13\$ 13w1ʉT$1ىL$ 13W3\D3\3D3L$13T$13w1É\$1ЉD$13_3TL3T3L3D$13\$ 13w1ʉT$1ىL$ 13W3\D3\3D3L$13T$13w1É\$1ЉD$@;|$:!ƋT$Ɖ1 O\$3L$ w L$ #1D$1ʋwT$*ڋD$ \$13W 33_ÐUSVWl$$t$(|$,^NV ʉ_OW HF^NV ʉG _$O(W,33_3O3W ] }7$\$L$T$ 13_3TL3T3L3D$ 13\$13w1ʉT$ 1ىL$13W 3\D3\3D3L$13$13w1É\$1Љ$L$T$ t$,33^3N3V w$\$L$T$ 13_3TL3T3L3D$ 13\$13w1ʉT$ 1ىL$13W3\D3\3D3L$13$13w 1É\$1Љ$L$T$ t$$|$,G_OW G _ OW G _ OȉW̉ G _  G _ OW _  O$ W(G, _@ OD WHGL_OWG _ O WG _ O W؉G܉   WG  O WG  _ O WG _0 O4 W8G<Dt$,F0^4N8V<3F 3^$3N(3V,w $\$L$T$ 13_$3TL3T3L3D$ 13\$13w(1ʉT$ 1ىL$13W,3\D3\3D3L$13$13w01É\$1Љ$L$T$ |$,G_OW G _ O؉W܉ G  _$ O(W,    艗_OWG _ O WG _ O WȉG̉ _ O WG OP WT GX_\OWG_ O W G_ O W G_W@GD_HOL W` Gd _hOlWG_O  G _ OW  _ OW  G0 _4 O8W< _p Ot WxG|_^[]ÐSL$\$ T$F> RQS, 1[Ðf;XzsL/7ƾOSTo'-hˆVpppppp,,,,,,'''WWW###kkkWWWEEE555 OOOAAA###kkk|||EEE>>>^^^!!! 999OOONNN]]]eeeZZZQQQlll|||ttt+++΄>>>000444___vvv^^^mmmũ :::999222GGG]]]SSS===ZZZzzzQQQ$$$VVVlll```MMMiii fffbbbTTT---dddttt+++ uuu ߇LLL444sss~~~vvvmmmRRR111сooocccXXX:::aaa)))///222xxxqqqSSS"""rrrDDD666***zzz<<<$$$@@@CCC```iiiwwwPPP'''}}}555bbb AAATTT[[[!!!NNNdddeeeҽďHHH000___uuuGGG=== ???VVVMMM \\\fff---JJJ 333sssLLLggg~~~111RRRXXXaaa&&&777;;;"""DDDoooKKKccc...PPPyyy}}}[[[nnn)))HHH///???YYYxxx\\\JJJjjj333gggFFFqqqԛ%%%&&&777BBB;;;KKK...rrryyynnnUUU YYY666IIIjjj***FFFhhh<<<%%%888BBB@@@(((UUU{{{ IIIhhhCCC888((({{{www888AAAXXXvvvgggNNN```rrr ®jjjuuu]]]WWWFFF'''Ɋ222KKKBBB''':::%%%III{{{ CCCqqq\\\___>>>>>>ggg|||```nnn///444 MMMSSSrrreeeꎎzzz---kkk+++666555MMM333fffaaaXXXZZZ:::$$$ VVV@@@xxxccc BBB333̿&&&充aaahhh???;;; oooSSSbbb...((( ,,,tttooo666"""888ddd999NNN,,, 000 yyyDDD"""eeeYYYkkk===###HHHtttQQQTTT000~~~(((UUUUUUhhhAAAPPPCCC111///˨***<<<+++ppp222iii bbb$$$GGGEEEsssmmm~~~)))JJJø...攔%%%!!!HHHfff{{{;;;qqq)))777ͱlllLLLdddnnncccvvv---KKK&&&}}}___\\\OOOFFF???777yyy^^^GGGRRRmmm[[[^^^iiiZZZ<<<111LLL 555󌌌###uuu]]]jjjJJJWWWՄ!!!DDDEEEQQQ}}}999sssܪ|||wwwYYYVVVlllTTT444xxxpppIIIRRR PPPwwwݓ䆆***[[[zzz@@@===OOOUSVWL$GD$\$T$$l$(t$z)߁)|$,t$D$\$L$ T$$l$(] E] M@U`ND$$t$L$ |$(T$_OW 33^3N3V ˋ|$$Nt$|$ɉʉ_OW L$ vt$WT$L$ #t$(OW ^NV d$_^[]Ü|$P)9 <1_t$_D$ )D$T$$;t$|$(|$,^NȋV ˋ|$$|$,t$ 33_3O3W Ut$ t$|$_OW t$,vt$|$|$,t$(_OW ^NV |$,_OW N|$|$|$,^NV _OȉW ˋ|$$|$(t$33_3O3W ^NV vt$t$,^NV _OW t$vt$L$ L$ i|$t$,<tى󤐐d$_^[]Camellia for x86 by ̸ D$HPSUhVW8p  H P P H H P  P  P  P  P@  9Gah D$3d D$3` D$3\ D$+ցGaډT$h 3d T$3` T$3\ X3׍ É|$3݋\$ۋ+sn<|$|$l$2MD$@EFKD$l$uۃT$L$+ljD$ D$+ЉL$T$T$$D$(RWPT$@T$4 Es%+>AT$ 3T(uD$ 3l$utDD$$l$(PWUT$@ l$L$>++(2K@uD$0_0^][YËL$0_1^][Y̸s D$ SUl$VWD$t,t(L$,t$2L$AF@ML$t$D$uԋ|$(w ΃rc;s+3D$$L$T$WPSQRT$HƃȉG u D9I9uu\$\$+sD$tp\$,L$$WQ3jCSCSC T$HΉw u D9I9uu|$L$t$++2M@uD$08_^][YËL$0_^][YUl$w3]S݃VWuD$(t$$L$ T$|$PVQ+URWl$0v+ˊ0@uD$ PVVT$4|$$L$$SWQq FGNOV W _^+[]S\$s3[ËD$L$T$Ul$VW|$$PWQ+SURu_^][ËL$v+ωt$$0@l$uD$ PWWT$4L.WT.GD.O _L.^][̸ p l3ĉD$D$0L$4T$8S\$,Ul$,Vt$8D$ L$T$w^]3[L$3op WujQP+VSU3WD$8D$_^][3o ̸ o l3ĉD$D$0L$4T$8S\$(Ul$0W|$8D$ L$T$s_]3[L$3o VjQP+WUS҃u^_][L$3ro 3V߉D$ D$$D$(D$,D$ SPo L$$T$jQRjD.PL$_^][3h 0̸vh |$ D$SUV0W|$(\$ t,It#T$ 0 >>L$ABFKL$T$uكr~T$L$+ljD$0D$+ЉL$T$T$$RWWT$@ s++>A$T$01(uD$03l$u6D$$PWWT$@l$$L$( >++(0K@uD$,_0^][YËl$ \$t/t>L$2Ј>AFCML$u߉\$l$ r{D$+ljD$0D$D$$PWWT$@ s3+\$+>AT$0(Ћ43*0ul$ \$D$D$0+3l$l$ \$ut;D$$PWWT$@L$(++σ >L$0L$0< 2шM@uD$,_0^][Y̸4Ff l3ĉD$0D$8SVt$DڍVW|$PD$D$LT$WUT$ WPT$(W WWT$4эF‹ |$Xt4~wD$׍l$,+++ËˉD$I 2\$) AuG3~AD$,+؋D$++T$D$ $T$L,,  2ЈD$E;|D$LȁyIAL$u0LT DHWP ]OW _^[L$03Be 4ò*шT$GtVL$L$L$ ӈWVL$L$ ÈFL$ ӈWVL$ ЃWu]L$<_^[3d 4̸vd U39l$vSVWD$݃+ϸL$0QL$"ЋD$(Ҁ T$T$,RPjQL$HT$&D$'ϋ|$0$">E Ѓ>;l$ r_^[]YS\$vAUl$(Vt$W|$+D$,L$$T$ PQR7jP͋RFu_^][̸c D$S\$UV0W|$(t%t! >l$2MD$@EFKD$l$uۃrvT$L$+ljD$ D$+ЉL$T$T$$RWWT$< s#+>AT$ 3T(uD$ 3l$ut9D$$PWWT$++(2K@uD$,_0^][YËL$,_1^][Y̸@vb D$D3SHHH Z UjVrL$$3l<3\3L 33l͋|$h_ OW/T_^[]ÐUSVWT\$ht$l|$pL$tL$t+SK[ D$D$ D$@8D$`$D$ pD$$lD$(HD$,TD$0D$4 D$8@D$<`D$@D$DD$HD$L൐3_ 3O3W3/\$ L$T$,$lL \1$3l<$3\3L 33lO>$3l<3\3L 33l͋|$p;|$t|$p3|$h_ OW/T_^[]ÐUSVW|$t$X_1ɉڈѽoDo ~sosD /s< M~ <sosDs< ~ sosDs< ~ sosDs< ~ s ~s ~~w_ WO/_^[]ÐUSVWD$\$L$T$ ^ ʉ$ $($,À$$SoCo[$SoSokGsosT$SoKs<ocWsooEs]T$SoCs<o[OsgoUsmT$SoSs<okGs_oMseT$SoKs<ocWso oEs]T$SoCs<o[Osg(oUsm T$SoSs<okGs_0oMse(T$SoKs<o#Wso8oEs]0T$SoCs<o[Osg@oUsm8T$ S(oS(s<ok Gs_HoMse@T$ S8oK8s<oc0WsoPoEs]HT$ SHoCHs<o[@OsgXoUsmPT$ SXoSXs<okPGs_`oMseXT$ ShoKhs<oc`WsohoEs]`T$SxoCxs<o[pOsgpoUsmhT$s<Gs_xoMseps<E]xo0XP 3Q 3Y1I$$$$1Љ$o|oĐ~soމs$s8|Đ2,~soމs$s8^|Đ2 <Ћ$~soމs$s8 N|Đ2,~soމs$s8^|Đ2 <~soމs$s8N|Đ2,~soމs$s8 ^|Đ2 <Ћ$~soމs$s8N|Đ2,~soމs$s8^|Đ2 <~soމs$s8 N|Đ2,~soމs$s8^|Đ2 <Ћ$~soމs$s8N|Đ2,~soމs$s8 ^|Đ2 <~soމs$s8N|Đ2,~soމs$s8^|Đ2 <Ћ$ ~soމs$s8 N|Đ2,s~sos|s<^~Ns s $$~oqqp;$($ P X0$,w_^[]ÐT$D$YofpNfpfofsffs?fffsffiffofofpNfpNfff:Df:Df:DWWfofsfsfffofsffsffs9fofsfsfffofsffsfffsfBËD$T$Yofo)f8fofpNfpNfff:Df:Df:DWWfofsfsfffofsffsffs9fofsfsfffofsffsfffsff8ÐUSVWD$T$t$\$ Y'ofo)of8Ł2oovf8f8ffofpNfpNfff:Df:Df:DWWfofsfsffRv fofpNfpNfff:Df:Df:DWWfofsfsffoffovf8f8fofoffofsffsff:Dfs9fofsfsffpNfffpNff:Dfofsffsfffsff:DRWWfofsfsfffo)v fofpNfpNfff:Df:Df:DWWfofsfsfffffofsffsffs9fofsfsfffofsffsfffsfąof8ffofpNfpNfff:Df:Df:DWWfofsfsfffofsffsffs9fofsfsfffofsffsfffsff8_^[]Ð  @8`$plHT @`FN V   ^ f(n0v8~@89;:H?><=P6754X1023`$%'&&h#" .!p*+)6(x-,.>/pBqsrwJv tu~R}|yZxz{lbm$onkjj,hibrc4a`ezd΀BƓJ ΔR֝Zޚb$揨j,r4z<DȮ LЧTؠ\"d*l2t:|GHASH for x86, CRYPTOGAMS by ̋L$QD$ ;P}D$L$ L$SUhVt$WyߍG+;FPV!L$ u_^][ËD$~96UPWVg~ t(t@KuuD$@D$t;tKu_^]@ [ø, S\$Ul$EVW{+D$y hhl jdjsj-_^]3[YËL$;APQ6 L$ tًE+ 3҉|$tU]8\$ t;҃+\$ B;+9l$uɅttz9Nuu;t:t6NNt*PQNtPQNtP Q uʋD$T$BB ~ L1uHB_^][YS\$ { Vt$Wt,~ tËދCN;|$;G8>~ t3Vt$SV u_^3[É~ _^[PWtVS1"}SVW" tG _^[VSW tG _^[SVt$^ W|$G 3tdtƋWV!})Vt$WV u_^3[_F ^[WVt$V~ t_F ^[WVt$V _^ ^[̸L6* Vt$\FD$ ~(|uhhl jkjkjT*3^LFD$`u@tD$ xuhhl jgjkj*3^LÃ|$ uAPV }3D$XtVPytD$Tt jP^LS\$hUWS'SR(S|$D$$PSS~l t3L$ VQtT$$RSWW(-t F;|D$l$;t WUD$$P"D$_][^Y̸# $@D$ t"hhl jBj}j#P$u$jPSU$WU!U0"U(" |$PL$VQ$$~ t"VSrUST$(C RUVD$(P膕 K$UVQW.0u$jRD$ D$=~ D$5=~ D$$O~ D$3ɃL L$~lUD$$PWWSL$I;~:IU DT{TPUL$$QSRP虗^F;|ɋD$$xjVD$|$ ,$$|$I$WPu.9D$uUL$$QVVVO|$뽽39t$~-O|($WR+t +ރFO;t$|ԃ|${u/3~)$P$L$$QPPP蔖tVF;|؋$RD$$P$L\QPPft($+T$D$D$$^U)D$ PD$ _][̋G;Ul$ V~ȍ43vL$ ʋ@;r^]Ul$;o UWu]V43vL$T$SL$@;r[o~t0uMo^]UP l3ʼnESVuFW3}ȉ}ĉ}Eu.hWhl jfj|j3e_^[M3q ]ËUR؃u"EjPpe_^[M3= ]ËMQ`EtE&EURVP6 r~ E.2~ EY~ E3DEMU ;ȉE< E}}G@ u#hO@hl QG Eփ?+W@jVu 3Ɂ }MEuE̸MMЉMM؋MEE܋EQxPWUuuPUR虙LE x u6MQP}"UEM RPWQUR^uGE MUQRPEPjMUQREWPQURUj΍}EUPj΍}}MUQRPQUR賘fEUPj΍}eH9EE~OMUQREPMQReEMUPQ΍}E@;EE|KÙ}3|USR5NK^_^[Vt$ W|$ ;F;G PWu_^ËV~.SUqyY )(pxX Jߋt$|$][Vtt uQPQP VWF G _^̋D$L$QSXUhl$ h VpW8l$)(ihihi h 9|$y|$y Yރ x_ ^]Q[Vt$W3;tNQWPg ~ ~_^̋L$A~u3Vt$~W})jV<t9t P'6>FD$3҅F _V^_3^̸F S\$W3|$;uD$;u_3[YËD$ȉL$;u {_[YUHVF;sVSL$(uD$t P^]_3[YËD$s{  I@Mu <3ouދC~ LuHC^]_[YS\$CUVHtRd‹t9W|$INƙ‹yIAGGu_^][̋T$JVt$ +Fu%AW:| +1;u H}3_^_H^W|$Vt$tqG ;F t3Ʌ^_L Uu hOV;/}]^_ÍQS|6 +ދ4 9;w rJ}3[]^_[]^_^_39D$ _̋L$}3ËSU‹؋VWyMEt$9^={;~ WVYu_^][ËF;}@;|~ͺ_^][ ̋L$}3Ë‹T$9B~V2yIA!0B~ L1uHB^̋L$}3Ë‹T$9B~yIA̋L$}3ËyIAT$;B}VuBpr2!0B~ L1uHB^̃|$D$txt@ @ ̋D$ T$VtW|$ L;t _H^ÍH|+0;uI}_3^̋D$S\$ Ul$Vu}+Ћȍ:u?A|W|$~ I9u&HDL;t_^]H[^][_^][ÍM|+0;uI}_^]3[W|$u3_VmtWVuV^3_Ë^_Ul$ VW|$3;o~DSUWv؃ttGFnO N [_^]SD0[_^]tWVhuVk_^3]̋FSW9Fudt@ hRhhn P- u_[ËFt QRW ~t P/>^ND$ F_[̃?tGSV$7>t VNuDPOB/Wu^[SUl$ ]t,VW>t VnuꋛDu_^EEE ][̋N ;Nu}Whhhn hH, u_SU߽S9uFD@>][uFF >~~_ËNDFF ~~_Åuu FDVVAN ̋N A+ʃN tJuN@NHuVt$V3FF F$F(^hhhn j,+3Ƀ ;uhhhn jAjjjQ3ÉHHHH HHHH H$H(W|$t t GPX-WJ-_W|$G$u:9G(u5G VPw^u$hhhn jmhjG$_@G$_Vt$F$tHF$^NFNV W<;s+~ _F(^Vt$~$uI~(uCWu$h*hhn jmjtjF('_3^jWF _^3^UVt$W|$;}L$NjD$D$L$D$l$jWPU#N_^]ËL$RWPU NNDD$S\D$$L$QD$RWPMQYJNC~pT$L$PWQU;JN~ST$BL$PWQURJNC~1D$HT$QWREPID$,CNn[_^]̸L$0SUVW|$8Ǚ+‹D$<,u'u(u$D$4L$0T$,PQRZ _^][Ã}RT$4t$,QL$4RPQVlL$PT$TPy jQs _^][ËL$0+PSRQD$0T$(L$D3D$,D$ +PUQRD$DT$4|$dD $\L$0T$+PSQRW\SL$(T$H+D$T$0D$+QSRPW(SL$8T$HD$(QURP QSD$DhT$ D$L$0RSPQWRD$(L$H+RUPQRRD$D/D$ L$T$0PSQRWRD$8L$HT$(PUQRPR(|$< |$@\$8ۃ|$\$uOQWS] 3CCC CCCCT$4D$0l$,RPU]L$T$@)L$<RQPD$(]u||$<uu|$@un\$8ۃ|$\$uW RWS[X j@jSQD$@L$ereeee6S\$0}+D$8T$, D$4QL$,RT$,SQRY[ËL$(UVt$tF>u;|$t1WR+hn LQVu>tF>u;|$uы|$D$jzhn jAjhjt WDD$t P|$utS_^]3[ _^][ ̸ VS\$U3l$ ;lb<-u CD$ \$VW= P3׃tLFQ׃uT$\$ D$;t;u2|$;u3_^][ UPD$|$;G PW<;u9+uW{_^]3[ Ëޅ~g}+3D$$qЃ wqwqw3O @ʋD$EoŅ~LuHGD$L$ G D$9_^][ ]3[ S\$ U37-<-uCVW= P3׃tILFQ׃uL$.D$t9uu3_^][jW;G PWuT$9uW_^]3[ø98T+ƃ u3 3t0@CtQЃ uhʚ;W] VW 33 uЋGo ~LuHGD$8D$_^][]3[Vt$ >-WuF80u%HXtxu|$ PWu_^Ë|$ PWku_^À>-uA _^Ul$ VW339u tD$jhn P; ur9uuL$jhn Q: uTS]xAUutL$jn PQ: uyɃy[_^]_^][_^3]̃=hqu"j j@hn jhXqhqXqVJNP?u^ËD$WPjjjV<L$ QVVf8_^̸WD$uD$QP_ÍASU‹YVyKCKhhn UD$( u$hhn jAjjD$(^][_ÍL$Q  $T$ jRUVtEluT3~NID$jPDD$~-U, )C;^|]t D$@_^[S\$ VsuD$ VPxF^[Ul$3W;|+ʉL$;t&;MQUL$ u_]^[ËC E D]Nt~" +D NЅL$_M]^[̸L$ UVt$F A W|$ Ǚ‹VD*;Al$  PQu_^]ÁSyOGD$F +߉L$$T$uFxW<(<H}Bvx6.T L$$N *}l$T$t$ QjRVL$(l* ʼni[~T2uHA_^]̸FSUVW|$ Ǚ‹yKCl$ +ÉD$E;UZ+‹T$D$ ;t';BM J PRcT$ u_^][YÅEM:+΍t$ rutlu_^]A[YË0L$ t"֋0L$ l$ ouދt7_^][YËD$jPu_^][Y̸S33\$9\$u[ËL$Vqx, UW<3 ыL$ S3Q PR$NT$}_]^[øUl$D$u]YS\${u[3]YVU +VSSt$(u^[]YW{x64L$UVQ/1 + Dt$y֋t$C_~ |uHCD$ ^[]YW|$ uG_Vt$ Fu WV^_Ã~ t%WVF ~tm39N N ^_ËLu@;F PV"u^_3ɍ;N|Nj;vAߋF;|@F^_̋D$uVt$NWu PV^t jV_^Ã~ tPVF _F ^Ãu9s+_F ^Ë39s3ҋ>):׋>A9:r)<u FH;uF_^Vt$NWtWT$uRV_^ËRQPP+t)F@;F PVu_^ËFu#~uF |$tFt PWF~D$$tF(D$(tF$N QR|$ F VWPQRuQ%lKtN QR|ubhahn jqhjEV(t%N$tQN WQNQPP҃t _^][ËV NWRQPPuut V33_^][UVt$ 3W;tr9ntm~unF~ u9ntF uD$UUPUUV1F u/|$N WQPPPt6FV WRPPPthhn jkjgj~ uF_^]SVt$>tg~ta~W|$uDFD$tNQPu3ۋV WRPD$PPju3_^[WVu_^[hhn jkjdj$^3[̋D$ L$T$PQjRJ̸S\$UVWSD$3ShS`3ۃ ;D$PW6F;L$QUF;E;u!9G9D$9_~u;UjUuCSUtSUUi Ut+9wu3 o L$ o L$D$} tE  t T$ډT$3SW?uCSW0tSWW t!9uu3E o L$L$ tu3u3}u3M #t T$ډT$D$ PWUUu4Njp 9w,}uM9u} tD$\$T$ R_^][u$Y̸&S\$$Ul$4Vt$4FW|$ u;xD$4H u9 u x U!UUD$,UD$,UD$(UUD$T{؃\$(|$0uD$D$4L$ UVPQQjVD$,6u D$$@PVD$,tD$$uL|$jVW ZjWG @T$ D$UVWRP{VPL$$QW T$jVRF D$UVP@ D$(WP"L$UVQS:UVSWWjWT$D$ L$8UVRPQqtmD$8UVWPP\tXT$8D$RPtBL$UVt$@QVt*T$ RVt7hxh4o jojyjD$t;D$0t PD$U(D$_^][ËL$Q?tT$B D$I|$}D$PXjjVPS>vVS| ~ u VSSЃ H{uL$QS$,T$URS t(u4D$@RD$Vhh4o jqhh4o jpthh4o jqD$$PD$PP L$UVQSS{u:u{ uhh4o jp]D$PWSL$ UVQW1u$T$jR UcD$_^][ËD$8jPT$8D$UVRP\L$ D$UVQPPT$ D$8UVRPPD$xu9u x 'T$UVRW\$(^u 8u tnC\$;\$$UVWWW/u&T$@WQRgD$8xL$jQU9D$_^][ËL$(QWO\$$+\$K~ $UVWW'KT$(UVWWRD$8UVWPPphD$(UVPD$(PPSKL$L$$hZ!uD$6D$4|$xu9u x u3PWuP;tkWp_^]3[Ãu>:u7uD$4jPHPWt_^][j^h4o jpjyjn_^]3[SVF3W~'t ~tVWW< tlVV ~+t$WW}tMVW}%NjWWYt)VVKtCFutSWW u_^3[Ë_^[̸DFUV3WSD$D$(SSS SD$(SD$8SD$4Sl$0 )D$Tu+D$ D$jPjU L$hQWT$\RVzF  uVW|ID$(OL$,WT$0G T$8D$4OSVD$0 PWL$H6lD$L$+D$;G PWtUMPSQRQF E\;u T$JVD$F$;t VPt$$Q軴_^][Ĉ̍ @D$T$L$ nD$nnnbnrnz nXnhn` ~nRs nbnr~Hs nZ nh~Hs nh~H s nh~Hs nh~Hs ~Hs ~H@ s 6nnЍR~s @~wÐUSVW1|$L$\$l$ Q֋CGG֋CGG֋C G G ֋CGG֋CGG֋CGG֋CGGց[  L$ ICGIGCGIGC G IG _CGIG=CGIGCGG։Y_^[]Ð PD$T$L$ nD$ɐnЍR~s @~wÐUSVW1|$\$l$L$ ֋CG֋CG֋C G ֋CG֋CG֋CG֋CGց Ul$MCGMvCGM]C G MDCGM+CGMCG։_^[]Ð 0D$T$L$ nR@wÐUSVWt$|$\$nVGFV GFVG FVGF V$GF(V,GF0V4GF8V< @\$uKVeGFKV SGFKVAG FKV/GF KV$GF(KV, GF0V4_^[]ÐT$D$L$ ÐUSVW\$t$|$l$ 1 NWKNWKN W K NWKNWKNWKNWK l$ M NWMKNWMKyN W MK YNWMK9NWMKNWK_^[]USVW\$t$|$l$ 1)) NW))KNW))KN W ))K NW))KNW))KNW))KNW))K l$ ))M NW))MKNW))MKyN W ))MK YNW))MK9NW))MKNW))K_^[]USVW\$t$|$l$ 1)) NW))KNW))KN W ))K NW))KNW))KNW))KNW))K l$ B)) M)) M)) M)) M)) MW)) M()) |$$l$$)Ձ)) W))KW))KW ))K W))KW))KW))KW))K T$$)Ձ))M W))MKW))MKiW ))MK GW))MK%W))MKW))K) "N)KN)KN )K  N)KN)KN)KN)K zl$$A) M.N)KMN)KMN )K MN)KMN)KMN)K NKNKN K NKNKNKNK l$$R MGNKM:NKM-N K M NKMNKMNK_^[]Vt$ W|$US1ۋ1ɋ1ËD$ыF1ՋWD$ՋHF1ŋFӋWŋӋWŋD$ӋhF 1ËFыWËFыWËыW ËD$ыX F1F ՋWFՋWFՋW ՋWD$ՋHF1ŋFӋWŋF ӋWŋFӋW ŋFӋWŋӋWŋD$ӋhF1ËFыWËFыWËF ыW ËFыWËFыWËыWËD$ыXF1FՋWFՋWFՋW F ՋWFՋWFՋWՋWD$ՋWHF1ŋFӋWŋFӋW ŋFӋWŋF ӋWŋFӋWŋFӋWŋD$ӋWh F1ËFыW ËFыWËFыWËF ыWËFыWËD$ыW X$F1FՋWFՋWFՋWF ՋWD$ՋWH(F1ŋFӋWŋFӋWŋFӋWŋD$ӋWh,F1ËFыWËFыWËD$ыWX0F1FՋWD$ՋWH4F1ŋD$Ӂh8X<[]_^ÐVt$ W|$US1ۋ1ɋ1ËD$ыF1ՋWD$ՋHF1ŋFӋWŋӋWŋD$ӋhF 1ËFыWËFыWËыW ËD$ыWX F 1FՋWFՋW D$ՋWHF 1ŋFӋW ŋD$ӋW hF 1ËD$сXH[]_^ÐVWUS|$t$11ɋ1ыF1ҁՋFO1ҁӋFӋoF 1ҁыFVҁыF_ 1ҁՋF VҁՋFՋOF1ҁӋFVҁӋF VҁӋFo1ҁыFVҁыFVҁыF ы_F1ҁՋFVҁՋFVҁՋFV ҁՋFOV1ҁӋFVҁӋFV ҁӋFӋVo F1ҁыFV ҁыFVҁыF_$V 1ҁՋFVҁՋFՋVO(F1ҁӋFVҁӋFo,V1ҁыFыV_0F1ҁՋFO41Ӂo8_<[]_^ÐVWUS|$t$11ɋ1ыF1ҁՋFO1ҁӋFӋoF 1ҁыFVҁыF _ V1ҁՋFՋVOF 1ҁӋF o1с_O[]_^USVW1|$(t$T$ߍd߉)%)1)ԁ^NV v6D$\$L$ T$t$_l$ nt$|$ l$11n'n.n]ool$nMnFs s AonLnDs ~\s I9o~\s s \ B1n$n.nt$ n]ool$nt$$nMnFs s AKont$nLnDs ~\s KIo~\s s nt$\ R9=wt$k|$ 1ɉ)D Ջ?kD$1ҐōI9ىl|$t$|$ D 1ɉT$L(D$ FAl Iŋ9ىlD |$t$Ł|$ 1T$l T$L(D$ Fl Iŋ9ىll Łl1L$ T$D(IT ;L$D$ 9t$L$ 11ҋ$L$ D$ AI,C; $Él|$t$,C|$ l ,Pl$T(D$ ˁFl ŋDll$Iŋ9ىll ŁlL$ 1t$T$D(T 9ىD$|IL$ D D 19ٍIZ,l I; $lځ|$t$|$ T T l$D$ YFl$|$t$ 1ҐDIDR!Љ! L Kd$_^[]Montgomery Multiplication for x86, CRYPTOGAMS by ́$?,$nnۉL$1T$1L$ f1щl$1fL$1sT$l$!s!n!ns!n s!ns !n s !ns!n s!ns!n s!nsn s$Ð$,?<$L$1щT$1L$ 1щl$1ՉL$1!؉T$!߉l$!1!13!,!11ʋ !11, !11ʋ  !11,!11ʋ !11,! 11ʋ !11,<1111$ÐR/#D$f:DD$ÐUSVWD$\$ oD$\$$oD$\$ 3D$3\$$NjD$os _s ^[]PwÐUSVWD$,\$4D$T$ D$0\$8$T$D$,\$43D$03\$8xl$($L$|$t$ 111؉]1u 11_1^U[E]GF(2^m) Multiplication for x86, CRYPTOGAMS by Vt$VFP 3F(F0^VjKh@ j4q u^VFPF(F0^Vt$t!VaFPXF0t V^Vt$W|$WVu_^ÍFjPzW~ F(_F,^SVW|$WPWڋt0Ul$UVՄtD$L$WPVjQ{bt]W[_^[̸薌SUVW|$,WD$WjWt$^D$( u WK\$ D$u W6؅|$t$(D$$VP}^[3]W|$u 'st/3;u G G_^[]ÃtWVSYv u_^[3]Éo tWqHPWy _^[]̸,f$DW3|$|$u"hh jfjvj舀3_,Ë$<VR}q$LPnqD$;u;u$8jQ@u^_,;t$D$S$TUS)~S~Sl$~S|$0~S$~틬$\D$< $tl$-[l$$TSRU ~ |$,5~ |$,"O~ |$,3DD$,D$=~ D$0=~ D$O~ D$3ɃL L$$D~ u $TRVu} Ƌ$&$TSPV$Vj Tƃxu$@jQsSMUQPVL$0~iT$SUVVRO;~=S|[L$SUQRP;F;|Ë$L~ u$TPVt}%$TT$uD$jPn^ Ul$W|$ ;t?G;E PUlu_]^ 39G~ U @;G|WU}S]K;ىL$+D$,u KD$N9D$tW+yNF+ȍՋ1t +΋1PD$L$(t$(@< D$uyJBʋȋD$1t +1hL$;El$ t9E[~ULuHE_]^ Ël$ L$IyJB؋t +ʅt T$ D$1~Ft‹yJBʋ +14t t1tDL$(E<uN̸6wS\$UV3Sl$uS vu^][YW|$G;F PVjO,  ,  ,  , l        Tal$~~DuO~D$ L$PVQx tSt_^][YS\$K3u[VqUW$ <+Lt;D$}l$\\\$@+Lt;D$}l$\\\$@+Lt;D$}l$\\$@+Lt;D$}l$\\\$@tN R_];D$^} T$ @[S\$ VWjS!j|$3?tǐPSltF<u_^[_^3[̸tL$$jD$PQ tD$ L$$RPQ hvh jjhjt3̸ tS\$0Ul$0D$ ;uD$WSVVWtFT$ URdtD$WSPVVPtyċL$VQ9_tD$[WiD$_^]YS\$UVWS3\h`Fh PƔtoVWS؃ t3;/L$$T$D$QL$WRPQWc_^][hdh jjhjjW8_^][_^][S\$U39+uD$ UP_E][VW|$ WhW>it( IQV;btT$D$WSVRPWh_^][S\$UVWS3P[hFh P薓tjVWS؃ t.;*L$ T$D$QWRP#W8_^][hh jjhjiW _^][_^][̸Fi3Vt$(D$D$9uPD$$Px^^SUW|$8WngWgWl$$gWgD$4L$0VQUI }uT$,jR ^zUS\gH+½;|LWVSS?BWVSS+.D$PSS$ H+E;~WVt$"h< V[ VhT [uPD$LPY_^]8~D$H;tVPMX_^]8S\$L;tC{| jSWu[_^]8Ë3ϋƺ+΍uL$WQU3T$ |$033ۃŋVÉL$L$,l$‹T$ N׋ȋ^L$ÉNL$$L$,L$ˋ^ L$L$D$L$Ë^N ʋVljN3L$D$N~@j PVVjh L$8VQ#NjэT$@## ȃ+΋1uT$L B1uH[_^B]8ËD$TL$HPhT VQn_^]8̸@fbSVt$P~ ^W>hP VUY|Vh ?YuPD$TPmW_^[@~D$P;tVPU_^[@Ul$T;tC}| jUrUu]_^[@Ëuϋƺ+I,(uL$WQSy3\$ T$033+ŋl$\$,+lj++ˋË^3ŋl$ \$0N++ˋË^3ˋ\$$ʼnN+ˋ^ L$ljN +ʋVL$‹T$,ljN+ʉ|$|$NjVL$ ‹T$0ljN+ʋVL$$‰NL~!+jT PVVr@}9@ +jp +RVVZ؋ׁJ%L jhp D$hd VuVVh _VuPD$dPT_^[P~D$`;tVPR_^[PUl$d;tC}| jURu]_^[PËuϋƺ+I,(u L$ WQS3\$<T$@33+++L$,+L$0L$$L$ Nj|$<++ʋ++L$0‹V3L$$L$(‰N++L$8‹V+L$<L$(‹T$,T$0D$PjWRN^L$+D$$+D$hx VRVh lRuP$PP_^[p~"$;tVPO_^[pU$;t>} | j UNu]_^[pËuϋƺ +΋,(u0L$ WQS 3l$TL$L3ҋ|$(\$H+‰D$3T$D$ӉL$D$V+L$ +L$$L$H‹VN+L$$+L$DL$(‹V N+L$(׋|$+L$HL$,L$ ‹T$jjWRD$,N ZL$N3+D$,D$0RD$(jL$PD$(F3PQ9ZNjڋV3+D$0QD$8D$,jD$,WD$PU߉FY+D$4ыN3L$8D$,D$(D$HӉF+ыNӋL$<D$0D$,׉F+ыN D$4D$0D$@ыN$F +D$@D$8D$4D$DыN(F$+D$DD$<D$8D$HыN,F(+D$HD$<D$@׉F,L~ Rj RVV9}2DRj +QVV؋ׁJ%L j h T$XVR#ËэT$`## ȃ +΋1u$ B ,1uH]_^B[pË$$Ph VQGc_^[p̸D&WVt$P~ FW>D$Tmh VNWVh( MuL$PPQ*L_^D~D$P;tVPJ_^DS\$TU;tA{| jS0Ju][_^DË3ϋƺ+΍d$,(uT$\@D$WP5L$3ыL  |@| L$jL$QVVjh T$(VR؋эl$0## ȃ ֿ+΋u C@uH]C[_^DËD$\L$PPh( VQa_^D̸ vUD$(L$$SVW|$3D$ D$L$u GtOD$,L$(T$ RT$(PD$(QRPVCt_#^[ Åu t VF_#^[ ̸ TD$ L$$RT$D$D$ L$ L$PQRD$F̸ TD$ L$D$D$$$RT$PD$L$L$$QRPD$術 ̋D$Pj`h I ̋D$Phh I ̋D$Phh I ̋D$Phh@ I ̋D$Phh@ lI ̋D$Phh LI ̋D$Phh ,I ̋D$Phh  I ̋D$Ul$ PS Gu3]Ã{~ ujS0stWWjVVWUjS? u,jSst1GWjV迍VjUjS tWjV裍 _]_3]̸RD$,xD$<1SUVW|$@WPl$,u WVQ|$,u WDQD$,W7QWD$-QWD$#QL$@t$PWQ݉D$0T$8\$,WRD$WVUP [v\$$WUVS^WVSSZJWVt$UV趆2WUVVZVSS%  { tL$QSS& T$t$0WRVSS%^VSSb& l$DjjUt$(SVDIjVqD$T$D$ jjRPVU$,'L$T$ QRVU'D$L$ PQVU)T$(RVUB GL$(PQ+D|hhؕ hG<tWSRG@j PJW@GOIRW|$SPD$4RPWуthW>+T$(RW(C+ȃ ~D$$QjPM t$&hhؕ jv hhؕ jAjhjLSJSuJtVU臞Uw ^]D$ [_Ë$Qd7LSUl$Whhؕ j j3n9~PuEh hؕ j jnh hؕ j j n ~PuD$PV^FP^PL$ QiSbnPT$Riu EYE~TuIu.h*hؕ j jSnh+hؕ j j @n ~TuD$PVw]FT^Tth7hؕ j j n_][h9hؕ j jm_][Ul$VuWUQSKq^]hIhؕ jj mWUVS)qhKhؕ jj m0^]̸,VJSV3ۃWt$\$\$\$ H;;UWHWIW It$XD$FPi;‹hqhؕ UsȉL$$|$D$PtAt)thhؕ jvpT$@D$DRPUQ28$T$@D$DRPUQ%T$@D$DRPUQ :L$$SUQ? #VRSP@|hhؕ hFtt$V8\$L+QV=+ȃ ~ QjSG l$hthؕ jAjfjzGWEWKEt$,tUVYVr D$]_^[,_^[,̸,FSV3ۃWt$ \$\$\$D;UWEWEWEt$XD$ FP7‹hhؕ U+pD$$Z|$OGD$@;~h hؕ jl:L$DSPQ; /VRS=|hhؕ hF~u -F(~u,F~u,F~ u,F ~$u,F$~(u,F(~,u,F,D$hNPQ-VUjjjSR+} t~d$*|$PFPWL t_L$VQRW|$(WAntDu 8u to|$WjUtG |$tNUjjjSQ|u\$hh jhj93tS 8S7_^][TjjUt t$3T$ F UjjjRP9|tN VQRe0uGrʃts)|$PF PW? NL$V\$QRWS0m/{u 8u{ tH|$WjUusG |$Uhh jxhj38\$$jjU0s N VQR/} FN NF T$F NRVPQR/A~(PFPST c(N PQW9 HT$RW|$,SW@,n~~~~~~ ~$~(~,F8~@~D~H~P~T~LQ$SVjVujV~(>tCF;|T$URFV' [_^][_^3]̋L$A9D$D$ 8PVq3~I Bt@;|;uhh jqjqjk&^Ã}hh jgjqjI&^Ã+;t$ ~hh jmjqj&^VRT$R9& ^hh jkjqj%̋D$Ul$H;~jIh jnjnj%3]ËL$V+Wq FWVi_^3]S3ۅ~$I>ujVC~5>tCF;|T$FURFVr% [_^][_^3]ËD$ }jrh jojrj%ÍH9L$L$ 9QVp3Ʌ~$BtA;|;t{|v<u@|uhh jsjrj$^Ã+;t$ ~hh jmjrjp$^ËL$VRQ$ ^hh jqjrj@$^jwh jkjrj&$̋D$L$;~jFh jnjkj#3}jLh jzjkj#3ËL$PD$PQ# S\$ W|$;~jZh jmjoj#_[Vt$+PjV#L$$W+QV#^_[̸t"l3ĉD$pD$x$U$VT$ RD$L$ l$3D$PUD$SW$3ۅl$jD$ˋӍD$,UPL$T$\$P $T$$QRD$0P;R jL$QT$0RR tkD$ ,0;jL$QT$0R R tF1D$DPL$0QQ t,L$+RD$DPQA" C;(D$_[T$ R1RL$|D$^]3!t L$ T$PD$PD$ QRPa̸ F!l3ĉD$L$,T$4D$$S\$,KW|$8L$K;T$ ~(j-h4 jnjyjS!_3[L$3!! Ã)}(j3h4 jxjyj&!_3[L$3  UVjph>T$LPD$jURPStm+σ)QUjR!L$+W@QP jV ~2jIh4 S J |$u*jLh4 jAjyjz ^]_3[L$3F  jVSW|څ~+ˍ$0@upPSUD$$jP|L$|$l$T$++++֍\$+ދƉ\$00X(0X0X\$0XuҋL$QKL$0F^]_[3 ̸<6l3ĉD$8D$@L$HT$TSUD$D$XVW3H)L$T$|$+\$\yD$3ۉD$\hj|h4 PH ujh4 jAjzjS4/jV(L$hT$QRP^\$(PUSL$DjQv,֍D$ 3+АD 0\0X\0X\0X\0X|蹜PjL$(QUW*~L$+ϋ0@uj~L$lT$PjD$@PQRPD$4׋+֋4;0s|$;}I<8u@;|;tw<8uq@+9l$T}9hh4 jmjzjWH_^][L$83m<UPD$$P WH_^][L$83>h WT$ h@؃ u hh jAhjD$L$T$PQRWSi~+ύd$0@ut+͸ 3;uG$;}F<t Ft#hh hhjA6$|++;t#hh hhj D$ jPL$0QC jT$,h RE l$D$$UPL$0QgE +tWT$,VRJE jD$DPL$0Q>E ttt$ō|$@r;u2stE:uv:V:Wu v-F:Gt%hh jhhjD$D$t SI@L$(Q,E$D$_^][3t̸,fSW3|$ |$9|$HuD$DD$HL$DQ؃;߉\$[Vt$P|$\$L$$+Q_AT$PjRD$0P?AjL$(h QB T$D$HRPL$,QB tT$VRD$,PB j+PL$,QB t|T$$RBD$TL$PQ+PSUTuV+t/D/@~3Ʌ~$T$0A@;|D$ t+ȸ EL$D)D$\$S=D$]^_[,Ë_[,̋D$L$T$ PD$ QL$ jRPQ̋D$L$T$ PD$ jQL$RPQS\$W|$+yjPh jnjj_[ËD$ Vpuj"k~GPhV t>FL$SQVs ^_[Vt$9t$L$u!FHL$VPD$ Pj@ ^_Y3Y̸Ul$ D$uh\ VZX3Ƀ]YhX V@XhSVY hD VXt RVY h4 VWchX VWMhSVY 6h VW GtAPVh VxWt MQVh h VKWhX V5WhSVXh VWGt PV hԥ VV~hhX VVhSV/XtJhĥ VV~8G t PVh h VV~hX VV]YËD$]Y̸vVW|$Pt$=uHSU\$l$\$$U؅t WNt UQ>][u(_3^YËD$u"hX QU!_3^YËD$tT$RPVLs _^Y_^Y̸D$ H$$|$L$$PjjQxS|$uqD$$RPx<|$uWT$ $QjjjR6 |$u7L$$PjjQh<$tjjjT$ PR=YËD$@YøY&E_̸ Vt$ PD$!=t&hh hhj^ S\$ 5u#hh hhjFUQ=t#hh hhjSD$u#hh hhj(RHPBP t u*hh hhjMt@PPPs؃ u*hh hhj؋FWt2PN}(hh hhjZF t1Pt#hh hhjL$4D$ QjST$RP^tcL$jjhjjQ~ET$jWhjjR~(D$UjhhjP~D$_]V\D$[t PZ:D$ ^ ̸S\$UVsD$P3UhjjV ^]3[ËD$:1WVl$XSl$$L$QjhhjV T$(RjhjjVD$(uS責D$(0u+S螬W+qWD$4EH uL$($_|$(t&讲G?L$(QP)S7v@t8 SP T$R v@tfl$8D$PUL$ QA8PUj3 8GT$Rjh>PGP8L$QPW3 tet$8t+T$R$tLPjhPV8D$PjhL$@PQ8D$D$t U7WD$_t P,D$^][^][V誅t5D$ PVt#L$T$WjQVRχVNj_^3^WjbPTujHhx jjtjY3_ËD$SVPjjjWPt:L$QVXt(T$jRVWCV;WBL^[_W31L^[_jch j$B&3Ƀ ;u3ÉHHHH L$@@AA A$Vt$Vu^ËD$ vWxGtPFu_^ËWVGF_^̃~ tËD$Hhh QPd%3҃ ‰F ̋D$Vpt)Ft PgF t P'V&^SUl$ EVuWxF_P莨\$(;t&hh hhjX_^][ËNQTr_u2~uD$L$ WT$RPSQj_D$FuLUtT$ F SRPNQqPV jD$0N WPQCS~ (u4D$L$ WT$RVPSQRqPD$tUNFNVPD$$QN RPQWT$F jWRPW PNT$D$ QL$(WRPQ | T$_^][VW|$ wFNWu_^ËGHV D$jQL$$RPQ |9VROpPGN 9;t h1h jdhja_3^ËFP`;t#h7h hhj._3^ËD$t|N WQPA lBWJT$QL$RQL$T$RQjjPoPw n|$ $VGHD$RT$QL$$RPQ }_^ËT$:_^̋L$AVqVWxFu*D$L$WPD$$QL$$PQRSoP_^Ãu'T$D$RPT$RjQ(_3^Ãu Qu_^ËF L$T$jWPQR~ƋFN VPFQL$ RPQWH3҅_^Ã~ u#hh P~P F tFN T$PD$WQRPHu_^ËD$ ;D$Cv L$rd$;)st,: vV:Qv F:A_^ËD$HPIBT$QL$ PD$QRPz| L$ ̋D$HPIBT$QL$ PD$QRPZ| L$ ̋D$t`u!hh hhjH3Ãu5QGmPu!hh hhj3ø̋D$=S\$VsW3H $lN|$QJ~_^[ËD$3|$|$;tGT$RWWPtD$ ;tPWD$WP\0D$;tP=uF_^[hJh hhj&_^[Ë|$OwINWu_^3[ÃuC uCt~usF~_^[hh h낍;w$VD$_^[9Vthh hA=uNT$_^ [ËD$*_F^[ËD$=}hh h_^[ËD$_F^[9Vth%h h=u(FtL$_^[ËVD$_^[ËL$_N^[ÍIGBmrW|$u"hXh hhj<3_Vt$x Ɗ:utP:Quu3p I:utP:Quu3u +h Ǎ:utP:Quu3u ` Ǎ:utP:Quu3u X Ǎ:utP:Quu3unP NJ:utP:Quu3u7L Nj:utP:Quu3u!jPD$hjjP\^_hmh jvhj^^_ù< Ɗ:utP:Quu3u#W$ L$jPhjjQ^_ù, Ɗ:utP:Quu3u#W$ T$jPhjjR蓾^_ù ƍ:utP:Quu3D$D$WPu^_ËL$T$ QjhjjR  D$P^_̸ Ul$Vu~u&FthPu^3] S[؅u[^] Ã}Wt|$UP3NWQRS_S~D$$jP| [^] [^] ̋D$HQsƒ̋D$HD$ID$HD$I D$HD$ID$HD$ID$uË@@$Vt$FPtPFPF< F<^̸v|$$|$ |$SUWVV/V'Vtc!PD$PUu tK L$PQW] t3VWUS t#T$VSRj"V}_][YË|$ Vi_][Y3Y̸UVt$$3uUu^]SWVV[|$0؃u hh jAhj _u=G OWPQR؃ u#hh hhjRu/Gt(9(t$ȸA$ PQuG<u:GT$PT$PT$P T$@T$  ƒL$D$ OG@WPBPVQSjguhh jhjUPE V|$,u VLu S_[^]Vt$FPW3;tP F< ~PF SgSD$0t P]$D$4[_^]3W|$G<@(t&L$ T$QL$RT$QL$RT$QRWЃ_S\$V| 3c bL$(T$$QL$$RT$$QL$$jRQPVSWc(^[_̸UV3t$wuGPV~tS_u؅G(uDL$QNT$VL$N T$VL$ L$$ уD$T$ ƋW URPGPStw_D$ tu S[tu VUD$ ^]Ë^]W|$G<@,tWЃ__̋D$pq̡pqu pqVt$F<@tVЃF@tPF@D$ F<@tVЃ^VWhḩ jD 3 ;uhḩ jAjgj M_3^ápq;u pqS\$F<;t6Su$hḩ j&jgj VN [_3^É^@;F@F@;t=P諱F<;u-hḩ j&jgj F@PV [_3^ËN<^4>~F~ ~~~~~ ~$~,F0Q SVjV(%F<@ ;t.VЃu$F@;t P]SVj%V{ 3[_^Vt$hḩ jF0jP<N_3^_^j)̃|$uFjHhP j ujKhP jAjrj r3ËL$@ø̋D$ L$T$hP PQR̋D$L$hP PQLv ̋D$uCL$ÃuVt$ R^ø̋D$ L$T$h PQRw̋D$L$h PQu ̋D$ L$T$hl PQR7̋D$L$hl PQ|u ̸ة ̋D$ L$T$h4 PQR̋D$L$h4 PQ,u ̋D$Phl AVt$W|$VW迼D$(PVWu L$_^hP T$RVtL$(V_^̸VD$u ^YËD$hP PL$ QT$RtD$ L$T$PD$QRPL$Qh^YËD$HD$%h)hܬ jjkj t W|$Du UT$RD$,PD$][_^,hhܬ jejkj p_3^,̸@SVt$X3D$9^ F9^UP2t2t*t"hDhܬ jfjqj ]^[@ËF P='~hJhܬ jgɍL$WQT$,RD$DP L$\9X9X VRP/vD$\@9Xf9X ]NQPHVD$\HWRQT$4R *L$X;~ȍD$PQL$\QU VWRD$0PL$ QRFl$\UWPL$0QRPF(tN WQV,jRQ؃F<@SWt#N QNT$4RQNT$(RQT$XRVЃ$#F VPL$4QNRD$(PQT$XRqS t@FWPL$DQT$ Rj脩t#EPL$QFt"t$hhܬ jjqj t WT$RWD$,PML$DQC _]^[@h<hܬ jejqj ^[@̋D$H(̋D$@,t PL̸ VtSD$,L$(D$D$$T$RT$ PD$ L$L$(QL$ RPQVD$ t^ V3^ øvD$ PL$QT$RD$ PjuË $VWQT$RD$Pjy D$u=D$HL$PT$Rj ucj^h jhjuj Ht"tjmh jijuj $_3^dujgh jAjuj YD$PL$ Qj u jsh jhjWFu7jyh jljuj t Wt Vt_3^WT$(VjtRv^_^̸D$ S3VpW\$ 9Xto9^ tj9^te9^t`mGPV=hh jAjvj D$ t PBt S%_^3[YË߿L$ QVFh뜋T$ PRSWjt@PD$(PBt_^[Y̸ &SUVW|$8WD$(PL$QT$3RV3ۉt$43D$$PL$ QT$ RU D$ 80L$uvD$PQU" U蟖SU蜖jU蒖?uT$8OL$|$T$88uxXPD$(D$PQj跂؃ tY{u&ST$RD$0Pj؃t*|$u#D$HL$,PT$0Rj uh%h jryjS/FuhY Fuh h jAFo|$ uhh jA)F NVWPFQRP!uPhh jmjsj L$4Qxt Sh U荗VW _^]3[ ËT$4VjtR][W7th UU_^][ S蟁_^][ ̸SVW3|$ 8uh:h jAjtj \$KFPQthAFSBjPuhKh jmjtj =L$ QW豀WـT$ SRVjjjtPD$,P& u2D$ t Pt Vdt W臀_^3[Y_^[Y̋D$HL$D$HQ T$̋D$@x txt xt3øS\$ CH WQu_[Vt$VB t P Fx KQRt.F@t P߽NySBPu^_3[ËNAt P諽V^z_[Vt$ FH W|$ WB QPu3_^Vt$W|$FPz}hh jijvj%_3^ËNQzVHPRz uh"h jhjvj%踳_3^ËWP uIh(h jjjvj%荳h Whص j{$_3^hh jCjvj%^3_^UWu hBh johj%._3]VhGh j( u!hKh jAhj%^_3]3FFF FFFFF F$\u8Ot /u8Ou3>$ʃ\H$pH+GnF ~nu+GN~VG+̓unN=N6+ͅuN)~%tu nF+N n N$GN39Fu9F uF9FuF9F$uF ^_]hdh jshj%诱V^_3]GGGHS\$ UVPd$@u5, W+h Sփu+h Sփuh Sփu hh3hGh W1 _uhh jmj}j%袰^]3[Sth V(  ^][h V(  ^][̸0l3ĉ$,$4$8$u DŽ$4IVh8  u4hh jlhj%^$,3ʯ0SW= h V׋؅u=VP hh jlhj%讯_[^$,3w0Uh Vh VjjD$ӋuVP hh jl.L$QWD$ $Յu3WH VP hh jrhj%<ID$,$D;r T$0;r7D$PWT$uWH VP 3$<]_[^3觮0WH VP $8P@u+‹$L~!;|p|$V$<QW覮 7F̸0l3ĉ$,$4Vh8 D$  u3hh jlhj%3^$,3߭0S Wh VӋutEfH fE J MVRPMQ ~ ~u ~u~ t$/\FtV RPU ~ /:GNVS+;~hʉL$+D$ tt/T$ BCT$ ;rL$L$ \$ +SP/R D$/\NV@+ك G;NV+;~iIʉL$+D$ tt/tuT$ BCT$ ;rL$L$ \$ +SP/R D$/\NV@+ك G;N$V QR/P N$ [͋]9_É\$ (\$ SUl$V33Wu*l$u~h+h jChj%P_^]3[Ë|$ōPI@u+h0@h P uh4h jA룋׋+Պ @uōPI@u+h;@h P6 uh?h jAP׋+Ս @u3ۋ8uhJh jA؅u(hQh jAhj%GV_^]3[Ã>u~uKNSVC F FuKNSV<\t~~~ ~~~~$~(~,~0~4~ F8QSVjVFD@ ;t.VЃu$FH;t PSVj"V 3[_^Vt$hh@ jF8jPNDAtVЃFHt P脂Vhh\ jAjmjFD$t Pt Sh_^]3[YËWjR@tčD$PWtFT$L$ W|$I9Hu 9x u9Pt >u_^ËHP 8QҋP¶>_^S\$t*V3tWFN >PV莶u_^[S\$t*V3tWFN>PVNu_^[W|$uhh jCjyjŠ3_Ëx(uhh jBjyj螊3_Vhh jD uhh jAjyjg^3_ËH(VуuV蘵^3_Ë^_Vt$t@,tVЃVb^Vt$t,H0tV @,tVЃjDVV ^̋T$Vp4uhh jBjrj蝉3^ËL$ ;thh jejrjy3^;u^QRփ^W|$u3_ËD$ VPXt&WVhuA,tVЃV\^3_Ë^_̋D$Vt$H8uhh jBjj轈3^ËT$ ;th"h jejj虈3^RVу^Vt$H3W|$(;uwD$ ;u _^3[UWHxWx;L$ t$Q^HSmjS`sT$(D$,WRPU蟅tWUVtRVЃ FtUPPmtfL$ T$(WQRSRtHt WSSVЃt/jU:t FHPUyp@D$WwD$]t PwD$_^[hhĻ jghjy^3[̸xD$Vt$W3|$ |$;tNHQPdlu_^S\$ Ul$(;u;9t\|$,uvD$u][_^ÅtWNtQSV҃tVtJWQUV҃t7-;tFtPSkt1;tƈVUktD$D$t PuD$][_^̋D$HD$h wSVt$W|$3ۍGH\$ D$\$;u/1uD$;u h+hĻ jAhjw`UVuVvVvVD$0vVD$8uVut=VWtRSWЃT$ VQRWЃ|$ 1OtQSjLjW|$$Wlj{u t|$T$$VWSR;toD$$VWSPU覃tZL$$jUQ袒 tFT$ VWRUt2jU诗t#D$$VWUPSJt{tD$]t VtD$_^[t Ps$ Vt$FPgNQgV,Rg F@^Vt$ W|$ FPOQ9iu_3^ÍVRGP itN,QW,R itӋF@G@_^̋D$@@,jPJj̸tV3W|$(t$t$ ;urD$;u_3^ËD$SUl$ ;Ƌt$t7WNHQP]S蚀tWSSVЃD$(t3WNHQP]S[t WSSVЃtzD$,tjWNHQP],S t\}0u:u }8u3t%tt WSVЃ WSSVуtD$ h@D$D$][t PqD$ _^øsSUVt$3Wl$9|$,u=qu_^][YËD$ \$tWSRPVЃD$$tWSRPVЃtyD$(tiW,SPV҃tYOD$ t$tNQPftGD$$tVRPft.D$(t,VPftD$t UpD$_^][YVW|$t*t$t"D$PdcL$T$PVWQR"_^hhĻ jChjr_3^̸rD$SW|$P3W\$\$t#hhĻ jjhj,r_3[Vt$0;uoD$;u ^_3[UV pVpVD$ pVpVypD$T$(t"L$V,RQWЃD$T$(B,x9x tEL$,tVRQWЃXT$(D$0@VRPW҃#D$,tRPdT$(D$0RP~dVOHQPS蚥u hUhĻ jhjpVu SUW GHPSU~D$,tT$(VURPWЃti|$0tZVuL$SUQWGHPD$SUP:}t-T$D$(VRT$8PRWЃtD$VPnD$]t PmD$^_[ø(voUl$KtqSOWQIPUtXT$(D$$L$ SRPQV3[D$u)R3PpJ3D$;t PV;t WzD$_^][̋D$uh h| johjjX3ËL$T$QL$ PD$RPQ̋D$uhh| johjX3ËL$T$QPD$PPR̋D$uh%h| johjW3ËL$T$ QPPD$RP6̋D$uh1h| johjzW3ËL$T$ QPD$RP̋D$uh=h| johj*W3ËL$PQJ̸ ̋D$L$D$L$UVt$W33u,Tu_^]VTV4US\$SP8MuD$ǀSPMuD$ǀPgSPLuD$ǀ0DSPLuD$ǀ !SPLu$D$ǀL$ T$VQRSP"hh4 hhjU[VSt WlS_^]̸&USUV33Wt$9t$t`|$tX9t$ tR\$$tJt$(u RtqD$ VSPW]tDD$VHHQWW҃t*'hh4 jChjT_^][YËt$tUR_^][YËD$_^][Y̸VTSUl$V33Wt$tS|$tK9\$ tEt$$u QޅtoD$ VPWc tCVMHQWW҃t-*hh4 hhj$T_^][YËt$tSQ_^][YËD$_^][Y̸ VPu^ËD$S\$Ul$W|$ WSUPVul ZȁuG%=t=u4hTVmPGtT$WSURV@uVc_][3^_][^VzNPt*D$L$T$ PD$ QRPVau V3^Ë^̅t-jihL j>| ujlhL jAhjR3É8@@@ @@@Vt$jhL j$FjPu^W|$tUhhL j$GjPpu7Vwt%tPFuOQO}WF}^_W|$tehhL j$GjPuGVwt-tPjV譣F uOQ|jW茣W| ^_ø&QS\${UVD$ l$u;L$3t?˅tD-T>+;T$rL-#ˋ;~h;}dt_+t D-;t;uHD$L$F>9D$$RPH؍D-;th.';t$vWh5h"h hhhL jDhjOL$ Q{^D$D$][ËT$(D$ 2^][̸\6OL$dS\$dVW33|$\|$X|$D|$1SPT$\2;\$$v\$$D$@D$;D$,4\$4|$(t$$L$HRPQL$xRPQz 3IG;r‹|$hE;l$,M$L$LT$0PD$tQRP!\$$t$@4u#$D$tT$pQPPRtk|$D$D$ l$|$++ljD$hD$h9(43t;D$Dt6|$@u"$T$tD$pQRPb 39L$DL$D|$@t%L$tPQaD$@)$ D$tRT$tQPPRD$@D$;D$-t$@tD$tL$pPQͽ!|$Dt$D$tL$pRPQ t%D$dhhL jAhjaFD$`t P0DD$Ht PD$4t P~qD$t Pmq|$ t$tPTqFuWAq|$Lt$tPػFuWqD$t PqD$d]_^[\̸(FESUVW|$;uhh jA,D$W3D$t P4t U7<D$t P/D$t P/D$ t P/D$(t P/D$t P/D$,t P/_^][$VW|$ ~m3ɸ 98t ACr9 ]=ĉQPQI PH u#hh hhjl=3_^WVm_^̋T$Vt3t$ t+CrC3v Wy<‹9|@;r_C^̸<UVt$3D$D$ u,U:D$ ujGh jAhj<.SV:VA;؃W|$VW訯ujQh jvhjl<GujXh jqhjH<VPW uj]h jkhj<W.tvVSW譬 tg{ujfh hhj;DVjjSUW膹t0UW8ujmh jzhj;D$_[t V9D$ t PR9t U5D$^]̋D$L$S\$Ul$VSjjUPQpnu^][WjIh Vd t#T$D$SVWURP9nuW~dt8Fht1~lu+L$ tD$tNdD$tV`^jqh$ jBhj73^̸ ̸ ̸ ̸ ̸X ̸ ̸ ̸ ̋D$L$h PQ ̸v6U3Wl$;;;t P%G;t PVS薭P@VL u&h<h$ jhjW6D$ ^_]Á8(u hDh$ jAhj6jjjUS%u hJh$ jhj5jU;GthQh$ j hj5\h wu&heh$ jAhjz5D$ ^_]SFSu&hoh$ jhj=5D$ ^_]WJFu huuVD$PSRFuhh$ jAwL$QP8uthh$ j Tu{T$RD$PL$QStTh Fuhh$ jA T$L$FHVD$BD$ t U%D$ ^_]Fuhh$ jA_3]̸3Ul$(Vt$(W3|$$|$|$|$D$;;9}9}S%؉\$$;%D$;V藪PAW=u4D$PSWV艥u;hh$ jhjJ3L$QSWVեuhS1$‹T$R$‹uD$D$^hh$ VD\ t$uhh$ jAVS(؃umhh$ jhj2D$t P]D$ t P]\$$3;t S#D$[;t P#D$$_^]Ét$uj|$T$ESRP R MVWQQ t$0~<}umBEuahh$ jA-hh$ W*[ |$ uhh$ jAL$WQ'YhE` EH V@F.3^ËuFt PuFth PW/tW1t'PCjFuh Vɹ3^Ë^̸F-SU3ًCVWl$l$l$;J9(B9h9C;9(9i@;9hSPUQR" |$;u hh$ jhj,C@PUQRB" t$uh 뾋CQG=#Sr=D$~#h h$ hhj,"zu h&h$ jAhj\,FP{G=uwFu h3h$ jshj",P06;~~VU#Wh;h$ hhj+m=~u hNh$ jshj+;6G;O;;~~~zVU#QU #WRU"GPU"jU"L$T$jQRU%hTh$ hhj*|=u hah$ j~hj*Uhfh$ jshj*5=C@u hth$ jshje*jPe0u hzh$ j hj4*} }U"=D$~#hh$ hhj)jVWUu hh$ jhj)QKytdF3Ƀ̸fSVt$3W3\$ ;9^U D$t~~ um tlD$PFUP tVUW4tG9_t^uNQM؃t)T$FRjjWSPЗt~ ^D$U t~u S貏t~ u Wo D$t PD$]_^[Yhh< jChj_^3[Y̸&Vt$ D$NFPQĔt"h?h< jjhj%D$^YUqFWP!CNVUQRƔ u hKh< jkhjFx SXu hRh< jzhjNUSQjWPCuhWpVWRuh\F SP[| hfh< hhj)rF NUjjPWQѕuhlh< jhj;VFURWPthrh< j{hjD$[Ut Wn_D$]^Yh9h< jChjz3^YVt$Ft PD$ P3ɃF^Vt$F t PnD$ P3ɃF ^Vt$Ft PΌFL$ PQ蝍3҃‰F^̋D$L$H@t L$D$ËD$H L$頊SUVWhh< j!j I9|$4t$$\$0l$,F WS UPj uL$WSUQV赉hh< j!j 8_^][̋D$@t D$<̋D$@uÉD$;̋D$L$ H̋L$D$!HVztD$PFu V3^Ë^̸6U3W|$l$ l$;x9oo9l$e9l$[V;@GSPW؃;OQ1P=uD$VV|$D$Vt2T$(D$$ORPSQ訍T$GVRUSPl0L$(T$$GQRSPL$WVQUSRʍtkD$ UP u;L$T$$QRr u%SWDt5Wt(D$hh< hhjVt SՉ[D$^_]hh< jChj_3]Vt$FHPNtQƈV ^Vt$FHP2NtQ)ƈV ^Vt$FHPNtQR3 F\F`FdFhFlFp^Vt$W|$GHPNHQu_^SWtR^tSu[_^UPUrtsO\N\W`V`GdFdOhNhWlVlGpFpF\;F| PSt)F\; PUu][_3^ËFx;F|}$ @;F||񋆌;}IU@;|][_^̋D$UVt$ WP~HW3Sj^\SW豛H t*t%hh hhj[_^]ËL$SQ~tW迗 t;F| PWtFx;F|} ,@;F||D$ SPWn t; PWvf;},@;|[_^]_^]̋D$Vt$W3tNHQPVu_^ËD$tVtRP:t!D$tƈVPt_^̋D$HPsHUVt$W33u* uhh jAhjISV V؃t%D$H\QPS t 9kt[t V1t W _^]Vt$FPNQy,Vp ^Vt$FPNQ ,V ^Vt$FPNQyV,Rp F@^̋D$ SU3tm\$teVt$WP~WtGUWN~SWtt/UW6~,~PWWtUWn@_^][hlh jChj]3[̋D$SW|$WP3t hh jjhjN_3[PO,QGt hh jBhj_3[Vt$tWRVt4jVNt$tWVitjV*^_[̸ V SVt$4W|$03VW\$0\$( tD$tVt$PhVyuGPVsu^_ËNQ^_V*pt5D$ PVut#L$T$WjQVROrVGv_^3^Vot2D$ PVut L$WjjVQrrVu_^3^̸Vl3ĉ$U$Vu^C]$3VĈÅtF~UD$j PUL$QW%8^3]$3 ĈVh W9} ~39$+ÉD$+‹+u/URD$j PD$ MQT$RW7lL$3;$ t QRh W|5F;$ujhX W873Ƀ ^]$3ĈWKP<uj^h j hj3_ËD$SVPjjjW>9mt:L$QVst(T$jRVWoVsW4^[_W34^[_WzJP<ujnh j hjf3_ËD$SVPjjjW8&mt7L$QVrt%jjVWoVKsWR4^[_W3A4^[_̸4S\$@U3VWl$,D$ l$4l$l$l$l$ l$$l$(l$0;u D$CF|$4;+SUtpD$Pt$HhPVk7 S PyPh8 V]zhX VGzD$,Sl$P[P运D$8=uD$Lt$uD$dD$SD$$BD$(1W9l$PtL$T$QRVSVD$L$PQVSUu D$S u D$T$$jRSS t6D$(jPSS t"SYTWjPVSD$T誧|$ u D$L$Q‹T$R;sD$P;sW;sL$$Qu;sT$(RV;sSSD$@t SSD$0h h  Vp t$P|$HhVW4 {D$8PPh( WwZ|$LtUS؃@hVW4 )SPh Ww L$VUQh   T$VURh WU`D$VUPh W8`L$VUQh W`D$D$t PD$t PD$t PD$ t PD$$t PD$(t PxD$4t Pt U D$,_^][4VDP$6ujNh jhjv3^ËD$WPjjjV2L$$T$ QRV_V. _^̸S3V\$ \$t$,;uD$ ;u^3[39\$(WVD$0V|VD$L$UQW 2T$URWW1D$4UWPP[Vt#CtPWSуL$VUQWWT$RKtQWS҃D$4UWPPt1VQWSЃUW|$uD$L$,t$$T$ SPQVRwD$(ULWQe D$ HPU|h됃u%}~ UtF39D$t hfD$,t$$L$ SUPVQNt5T$ SVRkR uhhH jkjgjoD$SD$t P+D$_^][ ̸ VW3|$ |$t$(;uD$ ;u_3^ 39|$$SUVD$0V{VsVkVD$DaD$;|$ L$(G\PQU[ r}VuG\PD$8RPj)USW҃6VSQSW҃SGtPSZ SUSZ VG\PS\$S_kuasȁu/%tu%hh` jnhjhh` jhju{~D$uD$L$0VSUQW҃t>D$;D$,tD$0UPPY t!L$0T$$VQURWMtD$V|D$][t PD$_^ ̸ SUVt$$WD$t/t*t%hh` jhhj_^]3[ ËD$$|$ PWOtDD$,t/|$0s%hh` jdhje_^]3[ _^][ W"F‹u ML$T-T$|$,D$9D$0s%hh` jdhj_^]3[ Ët$4uTD$D$4bVVVVNVD$$DWL$T$$D$ VQSRP1L6D$(L$,t;{t5L$D$ VSQWP҃~ tD$,S1+;v hvD$,V@jP" ~L$,RSE;thmD$(tuT\$S+;vh7vL$,VjP T$,PS;|$tChh` jDhjGt$HVD$t P _^]3[ ËL$4QrD$t PD$_^][ ̸U3Vt$(l$ l$;u#h5h` jdhj^3]ËD$$W8ǃD$ tttth?u ;thD;uBt$hLh` jfhjR_^3]ËL$$T$ QRWG_^]ËD$ SPC‹CtD;t%hXh` jfhj[_^3]Ët$4;uOD$;tVVYVQVD$@GD$JL$,UASQ 2D$$HPU2| hlh` jfhjSuT$|$(D$$VRUWPL$0T$,QDSPw D$$L$0HPQ|hy놋\$$uDD$0|$VUPWSуtw~t39D$t h9D$0|$(VPUWS]Gt8L$$VWQZJ uhh` jkhj[D$VD$t PD$[_^]Vt$HLuujMhx jBj}j3^ËT$ ;tjRhx jej}j3^t?xuD$L$PD$QPRV^ËL$D$QL$PQRVd^ËD$PD$PD$PRVу^Vt$HLu!ujohx jBhjH3^ËT$ ;tjthx jehj$3^t?xuD$L$PD$QPRV^ËL$D$QL$PQRV^ËD$PD$PD$PRVу^Vt$HPu!uhhx jBj{j3^ËT$ ;thhx jej{jt3^t3xD$L$PD$QL$PQRVu ^J^ËD$PD$PD$PD$PRVу^Vt$HTu!uhhx jBjzj3^ËT$ ;thhx jejzj3^t?xuD$L$PD$QPRV^ËL$D$QL$PQRV^ËD$PD$PD$PRVу^̋D$|q̡|qu B|qVhh j uhh jAjej+3^á|qu |qF ~uQFFt;P"F u+hh j&jej+FP蹬V3^ËN QFPVj V ^Ã|$u3W3._Vt$Ft P^FPVj jV'Vq^S\$Vh/h/h/SEu2W3_u^3[h/h/h/VS$^[Ë^[̋D$L$T$ PD$ QL$ RPQj ̋D$PfuÃD$"̋D$PFuÃD$̋D$VP%u^ËFtP=FL$ N ^̸@"̸|$ D$$vj{h jAjdj+U+`VWUU3U|$,'t$@VD$(ID$uhh jdjdj+YSV uVb=؃\$uhh jAjdj+ D$ L$4UPQjSVEuhh jejdj+oV>PtU=uT$ RWSV@u"h붋D$ PWSVQAuhVm:‹W艸‹;vhh jDjdj+Ohh V D$u hL$+SjQET$D$0SP@;thh jjdj+jD$W7PmSj=uL$QUW9uhiT$RUW>:D$$L$l$SPQU}l$$hh jhjgj*;hh jjgj*!l$$t VPD$t P?|$(u SϽt U肱D$]t P5D$t PD$[_^hvhh jlT$$SRVVIuhh jGl$0Et P蠰|$,t P荰D$El$$7D$4jyh jAjgj*jdh jCjgj*_3^̸薾SUl$4V3WU\$ \$\$ZUkU芎 D$ ;;;&D$;uhh jA~@D$$b؅SD$BD$USV. uhh jS |$4 ;~F‹T$D$,RWP> uhh jA ;~.D$+RPP uhh jt$4t&D$8tPD$Qu*h)T$L$_^Á_vjth jAjdj_3^ÍOFSۅujyh S& j{h SPuj~h jAjdj芴3[_^Ë+RjQF^蜴 [>_^Vt$ W|$ ;r+PGjPd 7_^ËO;rW+QjRA 7_^Á_vhh jAjij_3^ÍVGSۅuhh S$ hh SQP=u hh jAjij聳[3_^Ë+RjQG_蓳 [7_^̋L$T$ Vt D$Dv7IAHu^ËL$DtSd$HAu[^W|$u3_Vt$j[h VA uj^h jAjgj踲^3_VWPֲ ^_̋L$ D$Vt$W3vt IF@GwtP@u+_^̋D$ L$S3Wv 9tHCAw3Vt$vt HAFGwtƍP^@u+_[S\$u3[VW|$jKGh WO ujNh jAjhjı_^3[WSV _^[̋T$u3ËVp@u+PR^̡(#PŨuh(#P3hqj'SUl$Vt$W3^8SVW.~~~ F~~~~ ~(~$F,~0~4E ;tVЃuSVW= _^]3[_^][Vt$u3^juhT jF,jPCFtjjjjjVЃ~-N8QVj t@ t VV^{̋L$D$!H̋D$@#D$̋D$L$ H̋D$L$A̋D$Vt$tx tyS\$Ul$W~tjjSUjV׃~#~ u"hhT jxjoj 舯_][^ËH SUVу ~F0tPjSUhV׃_][^hhT jyjoj 9^Vt$u3^ËW~t{xtuS\$Ul$tjjSUjV׃~#~ u"hhT jxjqj Ȯ][_^ËHSUVу ~F4tPjSUhV׃][_^hhT jyjqj y_^Vt$ttyxtsS\$W~tjjjSjV׃~#~ u!hhT jxjnj _[^ËHSVу~F4tPjjShV׃_[^hhT jyjnj í^Vt$t~txxtrS\$Ul$W~tjjSUjV׃~#~ u"h5hT jxjhj \_][^ËHSUVу tPjSUhV׃_][^h)hT jyjhj ^Vt$ W}3D$;~t|$ hl WNtu u_^_3^Vt$u3^Ët[xtUS\$Ul$W~tD$jUPSjV׃~)T$ASURVЃtL$PUQShV׃_][^hhhT jyjgj -^Vt$u3^ËtVx$tPS\$W~tjjSD$$PjV׃~)T$A$RSVЃ tPjSL$$QhV׃_[^hhT jyhj 蟫^̋D$jjj P̋D$jjj PVt$uD$ ^Ã~$N$tx$H$uL$ H$tA(PjjV\^Vt$u3^W~$VjjV4F(tN$H$F$tV(P(_F$F(^̋L$QtII$tQuL$tP̋D$uVt$ ցt uu ;t@$u^̋D$uË@$Vt$t"W~,Ƌv$PRu_^̋D$H$Q PIH̋D$L$T$ PD$ QL$ RPQj̋T$8T$`L$8L$D$t@03̋D$t@43VjFhT j@ ujIhT jAjlj F3^ËD$PVu Vw3^̋D$T$ L$QL$D$D$ RPQ?̸膨L$T$ $PD$ QRPD$3ɅI#L$̸FSUVW|$3l$;jFhT j@ SVVtyGFONW V GFOjNWj WVvtbG8PN8Qj tU|$ut$ VU$eD$_^][Y&jIhT jAjlj § VD$t P_^]3[Y̸6l3ĉ$S$UV$W$,yVh D$hP=C= U$TBPh hL$*Q}PN$$t QRPQhl L$2hQ=NRPQhX T$.hR</$$t&N@QPRQh< D$2hP<HFQRPh( L$.hQ<BPh hL$*QB$$PQh T$*hRX<H$$QRh D$*hP.<hWh hL$*QNWh hT$*R;wD$t@~ Ct ~_^[ËvP>RV   _^[Ã>u݋st j S_^[̋D$Vp W|$uhh jsjuj x_^@thh j~juj R_^SUjPl$$<+WV;uD$NUPQF ][_^][_^̋D$SVW|$w H=0Y$YFGNt+_V^[QjP֡ _^[39_^[ËT$W_^[ËD$tXN_^[WD$ T$G W_^[ËD$t(_0^[Ë__^[ËL$O_^[Ë_^[3_^[Ð=X}XXXXXXXXXXX   VW|$ w jWD$H;}ȅ D$_3^Ëv3~<0 t@;|@t$PVW ~0_^̋T$Vp@u+PD$ RP ^̸%̋D$3@ HH A̋D$ ̋D$H wZ$Z3ÍIZZ̋D$uÍPd$@u+̸%Vh%u^ËD$L$ PQjhV^̋D$3ɉH @H @AVt$u3^Ã~t!~ t FPXF F^̋D$HV=\$h\3D$L$QjPRT ^ËD$HVjQT ^W|$ WYT$L$Gw O_^ËD$x tL$tPp^Ã^ËD$p^ËL$T$ƉJ^3^Ð[[G\R\a\c\["\[a\     ̋D$t t3ø̋D$tt3 t uVt$ 3tRWPD D$|$ OPVQLjW?"tu t u j W9_^VWjD D$L$|$ WPQRPjW"tu t u j W_^̋T$Vp@u+PD$ RP{ ^̋D$ Vt$ DD$;sfS\$ U-D WtRjՋKjVQLjS?~> t+F;t$r"tu t u j S+_][D$ 8^tPI@u+3̸%̋D$3ɉH HH @AVt$u3^Ã~t=~ t0F t)FPt(4 F FF ^Vt$39F L$ FF T$WPRjQt< uFt F P< N Q8 t;hh  Pj jhh jhj ߙ(_^Ë_^̋L$39A t>T$t6AVt$tA PjVRI QjVR@ t^̸&L$ SUVt$F IWl$v,d$dFjtT$$RP0 _^]D$[YËL$$QP\  _^]D$[YFPt$_^]D$[YX _^]D$[YFPt4_^]D$[YT _^]D$[YV\$$|$(#Չn - V~ ;r;shV6Ft(N ۀbPQ D$_^][YWP th@PL D$_^][YhPL D$_^][YV \$$#ՃVtjt h( D$ PHh <Ãtt!jh$ T$ R'tjh  D$ Pjh L$ Q|$$ OuGGuf f$GGuf f|$$L$QWH u_hh  PUjh T$0Rh Wh  jhh jjtj ޖ@D$D$_^][YhVF n D$_^][Yh{h jejtj 薖_^D$D$][YËL$$t_^]D$[YËF_^]D$[YËL$ D$_N^][YFPt8D$_^][YD D$_^][Y_^l$][YÍI` a:accccjacb5c    ̋D$Vt$ W3@t@ L$PQVP D$RPV`  t>tƍPI@u_+^Ë_^̋T$Vp@uL$+Ƌ39A t4t0AtA PjVRI QjVR@ t^U$#l3ʼnEE SVuEWuHI@u@ jj+xWVjhEӋJ =uMjjWQjhEӋ =YUERP6MUVPWQRhEӅtquƍP@uj+MQ@PVjhӅtJE܍URPd = ׃8t׃8 uMUQRH hh  Pjj*EMh Ph Qh  j , 8u1hh hjmj 3e_^[M3豒]hh jjmj 踒3e_^[M3胒]h%%u V4 3e_^[M3P]hW1VjjjWǍe_^[M3!]Vh%u^hVD$L$PQjjVM^̸&Vh&eu^ËD$L$ PQjhV^̋D$3ɉH HH HAVt$u3^Ã~t*~ tFjPx NQ| F F^̋D$Wawmli$TiVt$ VL$D$F~ V^_ËD$x tL$tP@_Ã_ËD$@_ËL$T$J_3_Ð7i@iKihiOi̋D$t t =3't3ø̋D$tt3t t t=3'uVt$ 3t[WPl D$|$ OjPVQp jW)tu"t t t=3'u j W_^VWjl D$L$|$ WjPQRh jW")tu"t t t=3'u j W_^̋T$Vp@u+PD$ RPk ^̸膎F(UW3|$ tD$ H$o~?t<:t t ~Mt$tCjl D$KjPVQp jSWt j S_^[S\$Vs >t ~Ijl D$L$SjPQRh jS!V$t j S%^[̸Ƈl3ĉD$D$S\$UVs HW|$4zlu$8u3 _^k][L$3蘇Ã>_^][L$3uÅD$0uN#uVu7 uF{ ^ _^][L$3Å;D$0k u1Ft PbWi_F^][L$3҆Ãu1Ft P,W3_F^][L$3蜆ÃuaOWGQRPQhh T$$jRFt PϱD$PF_N^][L$36ÃZRhd D$j PuFt PuL$QxFf_fV^][L$3څËD$0_F ^][L$3辅Ã{ t!tKk_^][L$3藅_^][L$3Ëk_^][L$3gËT$0_^]S[L$3KËFtPjjdWFtPjjdWF jPjfWN(QjW_^][L$3ËV(_^][L$3Մ3L$ _^][3辄Ë5ruttu!utur\rt6tru   ̃|$t3ËL$Q L$ J(̋T$Vp@u+PD$ RPK ^Vh(&Ut#D$PjjdVt^V3^̸P&̋D$3@ H HA39D$̋L$u3Vt$F$u^ËT$WRQPJjVV_^̋T$t7L$ ~/Vt$F$u^WQRPjVV_^3Vt$F$u^ËL$ W tKetT$RT$RQP_^jVRD$ L$V$PQjeRVe_^3_^̸x&VWjah j 蠫3 ;t$jch h脫 F;uVT_3^jeh h[ F;uFP(V"_3^ËD$ ~ ~~~Fxp _@ ^Vt$u3^W~ Gt P¬t W責F P覬_F F F^̸ր|$ u3YUl$ Vu }$SjUD$\$$W$~ t3;~FFL$WPQ~)~ |$ ;+|$;2VPE$RP U|UtcF~ 뎋L$U$SQR UP|t0t$;t(t$+ɋD$_[^]YËD$_[^]YËD$_[^]Y^3]Y̸|$ SD$T\$HUl$Vu 0}$&WjU~+~+~;Ftd~$VVL$WQR|$(|$ +~NFNU$PQR; UL~)~u;^F|?$D$M$SPQ U|LtZ|$|$+tN;^}ȋ~+~+~;9FFT$FSRP~L$ ^_^][YËD$_^][YËD$_^][Y^]3[Y3[YSUl$VW|$w Ey,$3FF FF$;L$ T$QRUWx_^][Ë^_^][ËN39^ ~rFv 8 uC@u_^][Ë^uN$`D$ L$PQUW_^][Ë^ u!$3T$ D$RPUW؃_^][Ë|$;>~0hAh W؃ Ft P诨^L$ VWQRF~ n} _^][ËD$ t8u Fl$D$L$.L$l$l$V~T$~!;.tD$hch PI t=D$=~Q;FtLL$hhh Q D$u-;~t Whh jAjrj ~|_^]3[ËF;tP跧3~FF .F;D$P蔧T$3FFD$_FV^][Ã$tjWL$(T$$G$QRUPRW_^][ËG$j~L$ T$QRUP_^][jW~~AINFNW$PQR|W^)^jWK~‹L$3FFD$ W$PQUR_^][Ë|$ jPjuW+tNjQjuW_^3][Ë{{P| ~~#|}{||W|     ̸zD$S\$UVp WjPD$Kl$$V N~LN33~;}UE< t@;F |@D$)F F+؅uuED$_^][YËT$PB$QP L$QE|tʼn~ FjD$_^][Y̋T$Vp@u+PD$ RP[ ^Ul$tqE;rj?u>>uhh Q莢M v QRP6y  hh PPM;sE;s T$ tE]ËE]̃|$ S\$Ul$VWD$$uD$ L$38t@<u+y3D$ t݅~'ID$$;D$(}L$j QD$,MދT$t2d$L$(9L$$}$T$PRD$$D$,@D$$u҅}"D$(9D$$}L$j QD$,E|_^][̸@vwl3ĉD$$%u D$$!Ë\$8PD$Pt$|$TG|$L|$$uL$@T$<t$HH;D$؉tHD$\$8D$jPL$ T$L_^I] [$ÃwO $L$G$L$GL$G L$GL$GD$$R tD$(ˊTAЉT$(G*uEGt$D$(|$LD$$.uhD$$GyQ t*D$} D$D$ÊLPЉL$G>*uUGt$T$|$LD$$Ã%H$4GD$ |$LD$$?lu_GGD$ |$LD$$GD$ |$LD$$GD$ |$LD$$GD$ |$LD$$hÉD$$ۃS$pD$ t'tt E^ F\$0ET$0T$<\$S\$ S\$0S\$rIxӊ,BV(Ќ        ̸jl3ĉ$S$(V$(W$(hD$$h h D$$D$ D$VL$,QT$$RD$,PL$(QT$8Rt$0$tD$PVW\VĕL$QT$$RW? U$ _^[3"j̸iD$PL$QT$ RD$PL$jQL$0"<$u D$=v̋L$T$D$ PQR ̸fiD$L$ T$RD$L$D$PL$ QT$RD$jPL$0<$u D$=v̸il3ĉ$$$S$UL$$3V$D$L$D$ l$~!d$D< tuKEl$$}3"t ~V$`j Rh Ƅ4\΋+W+Ù;}@3D$$h!$dRD$DPD$H贵Uh L$XL$4h0 Qh j([h-hd jwjij X8|$T$$RP|$ut U| $[_^]3Wt̸&̅t7Ft PFt P߂Ft P迦VƂYVw Ft!jPx FP| FG^W|$u3_ÃVw tCFt!jPx FP| FGKG GG ^_Ul$W$)tu9E$ڃ}$t _3]SjUNFENPQ؃uj UHE[_]Å|jS[UPWU+PW~t)jSuhh jijdj U4FtP5؃tWSutWUeut W[_3][_]ËFuhh jojdj pU_]ËVRPMt~ t4jWu%W| hh jjjdj "U_]É~}_]VW|$ jW¤w $uW ~&$tD$L$W$PQRڤW貪_^VW|$ jWbw $uW~&$tD$L$W$PQR:WR_^̋D$SUVW|$w H=At$<3ۉ__^][W'_^][Ël$ D$u&O Ft PU _F^][;u _N ^][ÃFt PϢ_n^][ËL$_N^][ËT$ O GFD$GO _^][à tD$ tN^_^][_^][à tD$ tV_^][Ë__^][ËD$G_^][ËL$_N^][Ë^_^][3_^][ 35¦#)3    ̋T$Vp@u+PD$ RPK ^Vh&et#D$PjjvV t^V3^Vt$hh j F FFz t43ɉHH HHH@HF F^3^̸&jjh  jz uËL$@A A AVt$u3^ËF t P|F F F^Vt$ u3^W|$ $u_3^jWKD$jP1D$ L$$;~ȅuj W;_^QO$VQX } W)_^UW|$l$Vt$~$u^_3]S^ jV蹟C~ CD$jP0D$ ;~uj V蚟[^_]ËN$UWQu } V膥k[^_]_3]̋D$@$uÉD$;̋D$@$uÉD$鋡̋D$@$uÉD$黠̸&hh0 j_x uËL$@D@A S\$W|$ jW\$z u_3[ËG Ul$Vq FFu19Fj WOF;w ^^]_[ÉF^]_[;sD$\$IN F;w+FWPUthh0 j{jgj F_^3[Ë|$uh h0 j}jgj F_^3[9~tFtPrF~_^[ËF_^[ËL$QSY_^[ËE_^[Ã>t~jF+F_^[ËF_^[_F^[ø_F^[Ë|$Q_^[ËL$|$_^[ËT$R_^[ËD$L$PK_^[Ã~_FF ^3[ËC_^[ËL$_^K[Ë6V B_^[Ã~F_^[ËD$VH _^Q[ËD$t@ xpxf_^[,JQaluu|سȳ! ̸'Vh'՚u^ËD$L$ PQjhV^Vt$WhhX j8F Fkm u_^j8jWD ~ _F^Åu3Ã~t*~ tFjPx NQ| F F̸6CN y(y,~PQ4I0MbijT$RhD$ FhP` }ht l Y̋D$SVt$ HW~ =8$L$D$_F^ V^[Ã~ D$tN^_^[Ë^_^[ËT$_V^[Ët$t_^[ËVWFGN O _^[tu _^[_$^[ËG$_^[Ë\$_$_^[Ët$t0_tFGNOV W _^[3GGGG GGG_^[t t\$t;~؋L$SWQA _^[Ët$mNOVWF G _^[ËD$O(PW,_^[ËL$QMbjT$Rh iD$FhP` ht l _^[ÍL$QT$RhFhPD$$H }h l _^[ËL$Mb‹T$i+i_^ÉJ[ËL$QMbjT$Rh#L$QT$RhZ L'u G _^[3_^[[dqʹҷٷ{A;   Vt$u3^Ã~t*~ tFjPx NQ| F Fv t VVj^̸>Vw D$~( ~,WSD$ PL$ QhhRH l } h Ӄ)L$Mb‰F0i+iN4D$Pp D$N(iV,+L$+yI@B}3ɍQF0u9F4t ;uK9V4|FMbi‹WjL$ QhhRD$` } ht Ӄ[^̸$v=l3ĉD$ S\$0UVt$4n 3D$ WPl 3D$D$D$D$ D$$D$(D$,~T$@D$PFL$QjRSP$ }u|L$Qjj,V臐jV}.u)t Ӄt t=3'uj VӉE b_L$,^][3<$SVW|$_ jl {tD$L$WjPQRh + fuL$WPD$SjPQR  jW;2tu+U-t Ճt t=3'uj W+ՉC ]_^[̋T$Vp@u+PD$ RP+ ^̋L$AT$Q;tAVWj}h j0e3 ;t!jh je F;uVf_3^É8NyVL$ zFx >~_NF ^Vt$u3^ËF A;-hFh RPNetЋN ɉFN S\$;}=|9;ËVWz| ++@< 9uVD$_[F^ËNT$[F^W|$t4L$ |,;}&GVr;}SW\A;Ή|[^_3_̋D$T$QRP ̋D$L$jPQ ̋T$t4~.JVpW9t3~SJ\ @;Ɖ|[ _^3̋L$u3Ë~HPQVt$t~NPjQ9 ^Vt$tFt PdVd^̋D$uË̋L$tD$| ;}I3̋D$tL$|;} PD$ 3Vt$t#~uFVPjQRt F^̋D$uË@VW|$ GPt8O Vjch QRbuFt PcVc_3^ÉFORQPq8WVG F O _N^jI̋T$SV23W~z\$9t@;|_^3[Å|;}+ iȉ dw`w'D$\$L`w=} ;~ `wgfff ɋ+3Ʌ lwuhh! jj (OT$$R ZUNBT$~jjPD$0PZjL$PQT$8sT$(~!+PQR[SD$8h8sP[ VQR}[ \$VD$,SPj[jL$0QT$VjL$HQT$,RWjD$LPL$8QWWT$@SRW+ 08sT$~$ +PQRWWD$(h8sPW j QR{W jD$t*P@u+@;sWVt$VFo ;rt_^3[dbu h0" Ӄu," >tBƍP@u+ƒ;s-WVt$VnWh V'oWh$" Vo$_^[Ët$_^[̡wt"PqD$wwËL$ w̡wu2VtVuwuVw^É5w^VW|$ 3t*W^tW!uW_3^áwt P=w_5w^̡wu6VtVwuHVcw^t @tСwtP9wwÉ5w̡wu6VqtVEwu Vkw^tt 5wáwu6V!tVwu@Vw^t'H t D$D$$T$ PRуÉ5w̡wu6VtVwu!V#w^t@t 5w̡wu6VQtV%wu!VKw^t@t 5w̡wu6VtVwu!Vcw^t@t 5w3̡X'PeuhX'Phx'j̸̃ v='t=D$PL u''M$L$ jQ='u'< $$T$jR Utl3ĉD$pSVW =s @=Ijjjh" 4 W 5 jW\$Hj WD$L։D$8D$DjPW VSt$P L$PQjVD$X  t$`t$Xt$\hh" VF D$<L$83ۉL$8~xT$DD$@h SjWjRjjP$ L$3T$RVhh* jj3(^̃=u?h'h* jj 2=u ) h*h* jj 2Vjыu^hh* jj 2T$RVshh* jj ~2(^̃=u?h'h* jj T2=u ) h*h* jj +2Vjыu^hh* jj 1T$RVchh* jj 1(^̋D$Pƻk Vhh* jj 31u?9t$tAhh* h@* =hp(hu?thh* jj 41^Vt$t*>t%hh* jjhz1^̸ =u?h'h* jj 0=u ) h*h* jj 0Hjу$uYVhh* jjb0T$D$RP3hh* jj>0BL$,QЃ,^Y̸ =u?h'h* jj /=u ) h*h* jj /Hjу$uYVhh* jj /T$D$RPshh* jj ~/BL$,QЃ,^YVh'h* jj L/*h)h* @jj *,/ ^hDh* jj /=*uhGh* jj.hKh* jj.hLh* jj . =*uhOh* jj .S UVWw>nu(U tj PWӃ G>>uX* E t~hlh* jj *,._^][Vt$t=WƈtF@tP6F@u_^j6^V>t#t  Q V҃>u^Vt$ >t*S\$ t  QV҃>u[^̃=u?h'h* jj D-=u ) h*h* jj -H̃=u?h'h* jj ,=u ) h*h* jj ,jу̃=u?h'h* jj ,=u ) h*h* jj [,Hjу̃=u?h'h* jj $,=u ) h*h* jj + Q̸=u?h'h* jj +=u ) h*h* jj +D$  $$BQЃuË@øF=u?h'h* jj :+=u ) h*h* jj +D$   ȡ$ $HRуuË@̸=u?h'h* jj *=u ) h*h* jj *D$ V ƉD$QD$P҃u D$t$QP҃u^Ë@^̸$tPD$P% $Q$=u?h'h* jj )=u ) h*h* jj )H$$RсĔ̸v$P}$=u?h'h* jj ^)=u ) h*h* jj 5)B$ $QЁĔ̸SVW39=u>h'h* jj (9=u ) h*h* jj (D$ P#L$QT$RB$ QD$ Pҋ;hh* h!/ ;t^D$ PV#Ix8u Q VҋءHVу;tV_^[Ę;t S_^[Ę̃=u?h'h* jj '=u ) h*h* jj 'H(VWiut7tFP/D$L$DŽ_^ËT$ D$_^ËL$ T$_^̸SVWh8h* jQP}-3ۃ ;9\$U\$~qD$ hD$tMōP$@u+;~ hGsh* FPW-t6NQUW6QD$ L$A;L$L$|jW]_^[W.]_^[;u3ËLDV;UW3DD8|H9t'tP.H9u dž;X_]9u3^Ãd^̸=u?h'h* jj $=u ) h*h* jj $Hjу$Vhh* jj p$T$D$RP=u/t&PDu Qhh* jj $HT$Rуt V^Ỹ=u?h'h* jj #=u ) h*h* jj #='V'tH Vу>u=((tIB VЃ>u=((t( $ Q V҃>u=tH Vу>u^SL$ \$[VW@%yH@;uAyIAL$ T$3|D$%   ‰DHD$T$H9t7t7P*_^É_^Ëȉ_^øUVWȉL$ 3~~;tF@tP#*L$>~@džuĉ_^]Y̸6l3ĉ$SU$V$W V-VD$VD$) |$D$uPh* $j@QQ|$uWh* T$$j@R5T$uSh|* D$dj@PT$\L$uL$D$u$$RQPVhd* WUߓŃP$@u+O;u3v.3=h j:P׃tT.;vD.:F@|ދ$_^][3Vt$ uD$hVP ^̋L$D$PQW;u3_SVpyNF\HDHttP'DŽDŽ^[_W ;u3_UVpyNFlHL$DHt(T$t u `*  HttP''DŽDŽ^]_WZ;u3_UVpyNFlHL$DHt(T$t u `*  HL$u3ttPo&DŽDŽ^]_ÅuD$ t^]_ÉD$t ^]_k;u3AyIADH;;u3ASVyIAt$ \Ht.W|$t$u`* _^[ÉH_^[;u3ASVyIAt$ \Ht*W|$t u `*  H_t$t3uD$ t^[ÉT$t ^[+9u3ËDH 9u3S\HVt$ t.W|$t$u`* _^[ÉH_^[9u3S\HVt$ t*W|$t u `*  H_t$t3uD$ t^[ÉT$t ^[K=QZלF-nt4A@B+2SpN8x^EE̸vl3ĉ$U$(VW$,D$P]L$ QST$RD$$PL$$QT$ RhL$(QPD$$ D$u T$PD$RPL$0QVh* $<hRb$D PI@u+UP$,P׃ ~$L$QT$RD$PL$Q+c$$_^]3̸@V[PD$PVEL$TQjT$jjRID$\PL$h Q菌d̋D$Ph`̋D$L$T$ PQR G ̋D$PhA̸ u&j"j " uYË *VWAPt$ *L;= *}cj!jVh* j j!ttjF F! VPj|!G;= *|t$ VQ߻L$tL$tHL$tH_^YjZh* jAjjj_3^Y̋+uc Wt->Ph;~ WPeKV@QRЃ_ËKF:utP:Quu3__̸(uËL$T$L$VL$QPT$ gtM t1W>P輺;~  WR踺N QNRPQ҃_V>^3^̋L$D$;uP@T$L$̸ VD$L$T$$$PL$ (h@QT$ʽ̋L$D$;uPVp @^̋D$QD$I:utA:Bu u3̸(Vt$ hAh* Pt$訿PKT$RD$(L$h@PD$ t$(D$,L$0L$ T$$hjQRt 3(9t$~!S\$(W|$0D$ WQF;t$|_[T$ R^̋D$t $|;uPQR̡(tiVt$Wx hP5$@ }6(PD hP!Q _( ^Ë(z _^̡ Vt$Wt/>P);~ WP&NQ҃ ȋ_3^ËFPɽȋ_3^S\$ Vt$ Q^[̃=(tj:hhp˽j(39(øSW|$3ۅu_3[9(u tD$ (V%D$ D$ PQ|$&t/xt2u.C P (D$ PQT$u^_3[Ë@ ^_[̃=(u7jPhhpj(539(u3hh* jO tL$HL$сVP(L$PRH EtI t0W>P*;~ WP'N QNRPQ҃_V^á(x\t3^̸S\$ CVW$ H @3L$D$ 3UL$,ÙF3;t$|ދ\$ ]_%?^ [ËR& _%?^ [Ë@P _%?^ [Ëx _%?^ [_^3[ R r  V+vR$ N +B RvWr;ustD:+u1v5Fz+u v$Fz+uvFJ+_^_3^Ëu^Ë u^Í$:utP:Quu3^^ËFtJt:ut݊P:Quكu3^ËF+B^ÍI    T$L$̋D$HA@H ̋D$@@Vt$FHFxu QV^̃=0u|$| 0̃=0t 0á,tLh P@ Q,h@ PA ,hP Q0,Rt,̋ $*L$ $*̸S3ۉ\$\$\$ \$9,u+h h |3Ƀ;,;u3[Vt$WVD;hh$j D$;tg9_ t!9^thh$j D$ ;tA9thh$j D$;t!9_tchh$jo D$;uGhh$jAjij3D ;t PF~;t W _^3[3D ;t",PR0x1;t PF~ЃgG_^[̸ D$$=w&t @< uh*I@  Ë ,tDD$$PT$ QD$T$ 蝸t@ h;h$jejgj3 ̸ vD$$=w&t @< uhJK@  Ë ,tFD$$PT$ QD$T$ t H h[h$jejhjH3 ̸ D$$=w&t @< uhjL@  Ë ,tGD$$PT$ QD$T$ mt HA h{h$jejfj3 ̋D$V0N @ +B urRvWr$;ustD:+u1v5Fz+u v$Fz+uvFJ+_^3_^Ul$VW33u_^3]S3ۅ~Kd$++‹D$|$ |$WPT$,}~^;|ͅtD$(uG3[_^]D$(t7l$ ~&~|$L$WQT$,uNt$[_^]̸SUl$Wj3USS\$/;_]3[YVhh$Wn u hh$jAjdj^_]3[YjUWVt7 $*A $*L$ QL$ QPVRs؃t S|$SV^_][Y̋D$L$T$ jPD$QL$RPQ`̸ l3ĉ$SU$VWhD$P3U|$W8 ; L$IL$ $L$L$Q t$R u>.uF>twFFPӃtNFQӃu>tQ$RӃuG8u?t-GGPӃt$OGQӃu?u33|$t2WT$VR tD$hD$PUH7  $D$_^][3 øvL$ W3;u3_ËA;,;t%L$L$QP|$ -;t PB_SUVYI;+‹D$, P}~~;|υuu ^][3_Ëm^Lm ][_̸8l3ĉD$4D$@Ul$@Vt$LD$ D$~|$PSWubV؃tSSuSt5tL$QWU0 ǍP@u_[^+]L$43H8ËF V3ɉD$T$$D$ L$L$33D$$@l$D$$utÃPQL$Ӄ ycu:vOuD$VQL$jQQ ~L$]U|$ taD$ Pr'tjPQ=L$Pkt|$~ 0]EL$D$tpQPI@u+‹t1\$~E.EKSWU;/ ;~ D$+މ\$L$T1WT$ ^Vh@D$0jPwD$8P@u+‹t/|$~'WL$,QU. ;~ D$+|$t$|$D$t PD$_[^]L$438ËL$t Q_[^]L$438ËL$<^E]338̸ vD$$D$ ,t+$RL$ PD$L$ ;t @@ SUVW3L$4)+‹ x ^_]̋D$3@HXH\̸T$  U3W|$l$8u;~JBO8t~"D:uO%yH@t_]Y;SVt$ BBZBB\$ B\$xNxJD$ uCx?D$  L$ F ˋFFF;vD$^[_]Y^[_]YVt$W|$t$L$PFPQ }_^_^̸fD$S\$D$W|$P~hhh Vw ;}T$ SRD8P ^_[YUl$$t=+VL8UQeWRG+ދt$,PV F@D$t$;_|/OQUVOT$ F+ك ;_DD$}хtSOUQ T$ D$]^_[YW|$3Ʌt+Vt$PGPV3L$ 0 @0^_ËT$ _øSUl$ EXMD$ E\V3҉D$ D$4W3D$T$ L$;;ut$46;‰T$j|$(P`D$4@D$4Ãƃ=t1P|hhh(L$ 3҈\)AD$(L$ =u |$uL$GuCT$(9T$D$@T$;D$8u>t;t53|)=u|)=u#G uÉT$(9T$tT$qut@|_tD$;~.QL$0EPQ D$L$|H+T$ 33;E};u,9T$E}#D$,D$@;D$8D$3T$0t$ 2T$_ML$$^MXU\][̋L$3AAA AAhhj t3ɉHHH HHSVt$ WjVAF|$tt/;%t Pٳ\$t1SHu1hhhhj_^3[ËP؅QS/u*hhhhj=SW_^3[Ë^;t}txDt V R`F>u\DtVGhFODhQS F u3hhjA6F떃>uhhhFt"VjjhjPm Ft _^[ËBVЃ_^[̋D$D$PVt$x@W~hhh T$ARVЋD$tQ@ tVjV&} QDF RjP _^Vt$t\x tjV}u H Vуt6xDt0~ t*jV|uBDN PQe!V R Ft P̜Ft P\3FFF FF^̋L$3AAA APAD$ PQ ̋D$ L$Vt$WPQVV_^W|$ /?&Gt)P-uh.hj&jnjq3_SVt$;u^ jV{3VWVGFO N WVGF t&ADttE^ BDO V PQR& GFGtWPFuGV^[3_hBhP) F uhEhjAjnj^[3_ËAt WVЃ^[_^[_h'hjojnj_3_̸3VD$D$D$ D$D$D$D$jP_zL$3[Ul$ VWU:#{`tX@ tOhhdPm E`u"hhdjAhj_^]3[Ë Q K`RQP @tP,UjjS҃_^][_^][hhdjohj~3[̋D$SUV3Wu t$FD$(;t D$(D$(t$F|$9nt;t;+;!;9.t^\VT$,V^\\$;t/S茥u/hhdhj{j_^]3[ËP{;tQS;uh뻋^n>G ;t9hhdP F`;u"hhdjAj{jY_^]3[Én`WVXn\@@t@UUUVu0hA9.u"hhdhj{j_^]3[ËAt!tthhhdS Vo|$(Vo%$$8nPVg~hhhd ;tVfPVWRVfPFPN QnP;tVfPWV RbD$ ;uA tL$(RQWPV҃=n ndH_INh^][Ë77v7s7s77̋D$xt D$D$$̋D$L$T$ jPD$QL$RPQ ̋D$L$T$ jPD$QL$RPQVt$tV1Vk^̋D$QyT$jRjPËL$9HXt ~t HXh^hdhjzj3Vt$ W|$ thjW D$L$T$PQRjVW _^̋D$xt D$D$Vt$ W|$ thjWi D$L$jPQjVW_^Vt$ W|$ thjW) D$L$jPQjVWm_^̋D$u8jOPh8  8%8̸&l3ĉ$SU$VW$$u=8t8$ =|$PSUjWVg$(t'$ =|UPSD$PjWVV]V L$hQ$ _^][3菾̸xFl3ĉD$t$$$SU$D$ $VD$$X Wx3@L$(T$ t$t$~hj~h| ~h`jh| 9t$ u_^][L$t3ԽxÍL$,QT$jRD$8Plt$$Ft$$tT$RD$HPL$4QU _$D$ RPL$4Q3 =D$(tjPT$4R D$PL$HQT$4R 9$vdD$jPL$4Q T$RD$HPL$4Q T$RD$HPL$4Q F;$rt$3t;tL$t TDAL$O@ut;t;ttLDMEK@uut1T$jRD$4Pi _^]3[L$t3-xË$QT$D$,PqL$Hj@Q%$D$$ _^][3x̋D$L$ T$PD$QRjPe`jY̋D$Wy9|$r;)|$SUl$Vt$3+D$P@`RP .QVվ߃;\$ v^][_S\$Ul$Vt$W|$@r<CPPC PC`Ph@WVl$8@@@űl$ tC`KPQS RPUWV_^][S\$ Ul$Vt$W|$@r=D$ FN`PF PQh@SWc@@@l$ u̅tVN`RF PQUSW/_^][S\$ Ul$Vt$W|$@r@FN`PFPPF PQh@SWDl$<@@@uȋl$ tVRV`FPPN QRUSW_^][̸膹L$D$;sL$SUl$VW;3D$߃+˺L$$ "Ҁ T$PRH @`QPjjL$'QT$*RT$/˸ ".G ˆ.D$0;rD$L$(D$$+L$(;sL$<_^][S\$ Ul$Vt$W|$@r?D$ FN`PF PQh@jSW@@@l$ uʅtVN`RF PQUjSW_^][̸̸̸̸L̸̸̋D$H`T$QRÑ|$tVt$jVx3^V^S\$ Ul$Vt$W|$@r=D$ FN`PF PQh@SWsR@@@l$ u̅tVN`RF PQUSW?R_^][VW|$@;stBS\$Ul$;r1CPC`KPQL$ S RPWQU0Tt$4+;su][_^̋D$Wy9|$r;)|$SUl$Vt$3+D$P@`RP .QVUH߃;\$ v^][_S\$Ul$Vt$W|$@r<CPPC PC`Ph@WVxUl$8@@@űl$ tC`KPQS RPUWV@U_^][̸̸̸P̸̋D$Vt$PVpbN`PQE ^̋D$Wy9|$r5)|$SUl$Vt$3+T$B`P .QVkB߃ ;\$ v^][_S\$ Ul$Vt$W|$@r=D$ FN`PF PQh@SW#9@@@l$ u̅tVN`RF PQUSW8_^][S\$Ul$Vt$W|$@r<CPPC PC`Ph@WV?l$8@@@űl$ tC`KPQS RPUWV`?_^][VW|$@;stBS\$Ul$;r1CPC`KPQL$ S RPWQU=t$4+;su][_^̸̸̸ ̸T̸$V$u&V.`%tV`%u!F`$PQ A^Ë$T$RP@N`QT$RBD$hP^Ul$EWx9|$rPL$)|$SVt$3+ΉL$ L$E`URRRPQV荺߃;\$ v^[_]S\$ Ul$Vt$W|$@r;F`NPQV RQRPh@SW~ @@@t%F`NPQ VRQPUSWC _^][S\$ Ul$Vt$W|$@r;NF`QV RQRPh@SW^ @@@t%F`NQ VRQPUSW# _^][S\$ Ul$Vt$W|$@r?NF`QVPRN QRQPh@SWڻ$@@@t)VF`RNPQ VRQPUSW蛻$_^][̸&W39|$SUl$VT$߃+˸L$  "JQ$D$B` RRQPjjT$/RD$2P$D$7˺$".G Ѓ$.;|$$y^][_YS\$ Ul$Vt$W|$@rMD$ NF`QN QRQPh@jSW蓼$@@@l$ ut'F`VR VQRPUjSWO$_^][̸̸̸̸X ̸ ̸ ̸ ̸(!̸\!Vt$F`W|$PWN`QWv` _^Vt$F`W|$PW輪N`QWR謪F`PW蚪_^̃|$tVt$W|$ GXPV豎_3^VOX| NQ=X| V+_^ø$ S\$ Ul$Vt$W|$@r=D$ FN`PF PQh@SW @@@l$ u̅tVN`RF PQUSWO _^][VW|$@;stBS\$Ul$;r1CPC`KPQL$ S RPWQUt$4+;su][_^̋D$Wy9|$r;)|$SUl$Vt$3+D$P@`RP .QV߃;\$ v^][_̸!̸!̸!̸,"̸`"̸"̸"̸"S\$Ul$Vt$W|$@r<CPPC PC`Ph@WVhl$8@@@űl$ tC`KPQS RPUWV0_^][̸0#̸d#̸#̸#̸$̸4$VW|$;stTS\$Ul$;rCC\ tNjKQSPRS`K QRPD$,PUt$4+;su][_^̸h$̸$̸$VW|$@;stBS\$Ul$;r1CPC`KPQL$ S RPWQUt$4+;su][_^̸%̋D$PXH`D$QRP }jvh8%hhj蕩3ø̸T%̸%̋D$Vt$PVPVN`PQ3% ^̋D$L$ T$PD$QH`RQD ̋D$VqWx`tu:|$u3PXD$WRP3Ƀ LJ@I*BPXD$WRPc LJu LJ*3ɃI0_^}!hh1hhj?3ø̋D$HQL$P @`RT$PD$QRP̋D$L$;JrP@`RT$PQL$QRËL$D$Vq`W|$u u _^ÅtuIXSVQPihVSGdž0u9t%xt|RWSH dž[_dž^Ãt|PWQiH|xRWP1 _dždž^S\$ Ul$VW|$w`u u_^E][Å|$ Vt$GXPSodždž"OXQSkdž@dž%GX R+QP džt$EG MO$UW(E G,_^][ËD$S\$VW|$w`u u _^C[ÅtUOXVQPhVRPQJT |$u@džt#+ RSW蚥 dž_^[̋D$Vp`WytuW|$uPPXD$VRPt#躺3Ƀ džIqgjdžNPXD$VRPt# 3Ƀ dž0I!jdž@3Ƀ I_^}!h7h1hhjT3ø̋L$A`t%VqV QL$PD$ PD$ QP҃^ËRT$ QL$PD$PQR*̋D$Uh`Wy9|$r VW|$ G\ w`t3OPD$QL$WPRT$ WVPQR= _^S\$rEUOT$PQGPPG PD$,VhRPh= u]t.WQRT$GPPD$$ WV QRP*= [_^Vt$FPD$F`t4QL$ QV0RT$ N QL$ PD$ RPQD.T$( VP^ËQT$ RN0QL$V RT$ PD$(PQR,D$(FP ^%u%$&uX&&u&&u('\'u''u',(u`((u((u0)d)u))u*4*uh**u*+u8+l+u++u,<,up,,u, -u@-t-u--u.VW|$ w`hxPx ;t V_^̋D$SVW|$w`._$^dždžQ x_|dž^[Ë\$_^3[Ã~;;|~3x ;t P#hh1S0 xt_|^[Ë\$CwuL$SQ0W豝 _^[ËD$Ph^QPD$ 0WPi _^[Ë\$u.|T$xQRP< _dž^[Ã|+˃tT$xSRP t|x+QRx}_^3[Ã|xPQR=L$$ ~ |;~|+xQPD$$Pd|x TLH uu_dž^[ÃD$|L$P+xQR|xPQR<_dž^[ù 9L$D$W0PW4PW8@ G<G;O< uGuT$jRSFT$ 7 +Ћ<;8usvVU^k̋L$Vq`W39ti9|D$T$PQL$ b_^9t@Q;u9|1D$;L$;u#|$WPV: _^;׋t;;׋|$tRWQPV|@tQ_^WQPVF;t;_^Á;׋|$tRWQPVABt_^WQPV=u'_^Ã0;u!RQPD t"_^jQQE dž_3^D.ux..u./uH/̋D$@`39L$tÉ̋D$ S\$ VW|$w`u u_^C[ÅdžVtg|$ tGXPSkdž0OXQS豫džGX R+QP%dž0e|$ tWXRS$[dž@GXPS[džGX QR+PZdž@D$$ t#W HO$PW(@ G,_^[̋D$H`UW}txT$ tjS\$VtYT$tQt$ rHt PD$PWVSRу^[_]ËHQVSR PUZMu ^[_]^[_3]_3]|/u//u0̋D$T$Vr`Wg$g3G_dždž ^ø+D$D$Hw_^_3^S\$u!C wJD$3;t;u;u ;u [_3^;tSP0Rdž袓 [_^39zt9tL$T$QRPK o_^_^Ëe(ffRf3ff̋D$S\$VW|$w`u u_^C[ÅVt2OXQPh0VRPQA:WXRPWh@VPQR@dž@dž t#+ PSWE dž_^[̸ 覑l3ĉD$D$$L$(S\$0Vp`WD$L$ uu_^[L$3舑 Ãxu t܅utu@\$<+SQ PWb@u_dž^[L$31 Ãt$ trD$P譪7F t{jU LtJVP~=QjjhjVH~"T$$RT$D$4PQRVPVG_^][L$`3yd3ҍN,t9Et4B|jmh9jnjljy_^][L$`3ydËF(u*jrh9jijljy_^]3[L$`3TydËM$QL$RT$QRL$@QRЋ$_^][3yd̋L$tA t @4tL$3̋L$tA t @0tL$3̋L$tuT$A| Q=t3̋L$A t @@tL$3̋L$T$;tËA t@Ht T$L$Vt$W|$;t_^ËF t&@Ht WVЃ~N At WVЃ_^ø_^hh9j 3Ƀ ;uhh9jAjjjw3úHPH HHHPVt$>th h9jjyjw3^ËFPQDF^Vt$>tth4h9hjxj^w3^ËFPF^Vt$>t"hJh9hhjw3^ËFP\F^Vt$>th`h9hjwjv3^ËFPF^̸fvD$VPL$Q?t03D$t PX^Y̋D$VPL$ Q>t03D$t PsX^Vt$ F t@ tL$T$QL$ RVQЃ^ËT$W|$ hRWPɌPh9h9W _^Vt$ F t@,tL$T$QL$ RVQЃ^ËT$W|$ hRWPYPh:h9W _^Vt$ F t@LtL$T$QL$ RVQЃ^ËT$W|$ hRW!PPh:h9W( _^̋L$A t@XtT$RjjQЃøVt$ W|$ ;thh9jejgjt_3^ËF t.@@t'VЃthh9jgjgjft_3^ËF t@DtVWЃ_^̸sSUl$3W\$ ;tP9^t*F ;t@T;t VЃ^F;t PV^;nu 9^ F;t PU^;tD$PL$WQ< T$ UR<;uD$ ;t PU;u%hh9hhjvs_]3[Y;tD$ ~ Fn_][Y̋D$Vt$jP3^̋D$ L$Vt$Pj^̋D$Vt$jP3u^ËD$3ɅF^Vt$jj3u^ËD$ 3ɅFt P]?^Vt$jjt3@u^ËD$ 3ɅFt P^Vt$jh3u^ËD$ 3ɅFt P*W^Vt$jj3u^ËD$ 3ɅFt P^Vt$tnhh9j FjPPF t@Tt VЃFFtPSFFth>Pu:V謜^̋D$V38tjNh :jjhj/q^Ë@L$T$ jPD$QRP辁^̋D$V8tjNh8:jjhjp^Ë@L$T$ jPD$QRP荁^̸*k3;u3ËL$A Q QVt$u3^ËF P躣F F F^S\$ u3[UVt$n tRF$tKL$WQSP" ~ t~WSU蛟 _^][jV褿V _^][^]3[S\$ W3trL$~jUVt$n tF$t QSP` ~ t%~!WSU ujV*^]_3[Ã~$tjVV< ^]_[_3[S\$ Vt$ F KWw($$~ tGjRP ~D$L$V$PQSR_^[Ã~ tL$_^[3_^[ËT$~ _^[Ã~ tD$F _^[jVEL$$T$ F$QRSPVY_^[ËL$jQPC u_F ^[ËT$J PQmy_^[ËUq6̋D$@ T$ ;Q}3ËT$L$QRP ËD$̸*jthp:h\ _3҃ ;u3ËL$PP P@@PA A QQVt$u3^ËF PڗF F F^̸lU3l$9l$u3]ËD$Vp ;9h$jP9FtFFP.nn蠔;SW;F}h:hhp:X >+~\$,;~Nρ|h:hhp:% VL$(WD2|PQk~F|$4+߃ |$\$,9u .n\$,;݉l$9nFL$$+RQ$0ZPRT ;,D$$H$jQ|$ K~9n?3~^9n<T$$jRĺtn+9nZD$EE< uI~ t F 8+QWT$$RN|FQP!*|$u#~tFPD$@;ÉD$|>Z;t!+׍Z3~I8@;|FP輒F9\$uMZ;u'uF F39l$,;t+3~ 8@;|nF3 }9nD$$jP{F|tiWZUP; D$~7Y=uH7X=D$uHD$;t+S /QU  D$ ^~3SZRVPFP貔n;ʼnn|=>\$,;~L$(WF|PQi|$ ~;>u.n+|$(\$,l$.T$$R踾D$_[;u D$^]3^]̸6hSUl$Vu Wj3U\$=9FtFFP^^܏~|h<;hhp:謊 >~h;hhp:荊 ;N}h:hhp:o >+~;'l$^;t \$ 3_^][YËl$VM$WD|PQ芸؃ ~m;~h ;hhp: ^~~h:hhp: ;V}h:hhp:ȉ +{3QD$P*_^][YË\$ L$jQF~h:hhp:N +~;~VW2ZUPf~F|$ PZQV|R4 =~h;hhp: ;F}h:hhp:ƈ FjVUUU<@WN|UQ =~h;hhp:r ;V}\h:hCWUVF|PNQ >~h;hhp:- ;V}h:hhp: |$+߉\$ FFT$L|B$SQP9 ;~h ;hhp:贇 ~+߁~~h:hhp:菇 ;N}h:hhp:q w|$ FD$_^][YWZURd |$D$~_^][YËD$P蘺D$_^][Y̋L$S\$Vs AWdwd$D~~FT$D$RPQK$Q膷_^[Ã~~ً;V}h:hhp:舆L$ >+~u<9~t;9~t6_^[Ë;V}h:h hp:JL$ >+~D$T$PC$RQP_^[3;Ntd$WWS ;N;VujSNt%F;t>PZPN|Q ~~9~t9~FtVV|RP~脎 넋D$L$T$PC$QRPW_^[jSƲL$$T$ D$QK$RPQ.Sָ_^[Ð+sߕƕ̋T$Vp@u+PD$ RP ^̸*VWjphd;h]3 ;u_3^ÍFPtL$>~~ FFy y_q ^Vt$u3^ËF P藚N hQyV RF F F^̸`D$ $uYS\$ Vs `{$VUl$W>~C+~;~NWRP!a~F|$(+ |$l$ 9u FI~C$hUP 9K$jQmVVSR~ FF"WUVFSP|>Ft4>l$ ;~~CWS\$$SO`|$+ ߉~l$ \$l$ \$9|$u |$\$jS讯SصD$ _]u F^[Y3^[YS\$Ul$ Vu WjU\$e>+~~/FU$W0QRT؃ ^+Ջ\$|$FD$WPVPFPJ|$,+ߋ>\$F~+NE$W1RP˯؃ ~@^+ً\$FU辴D$_^][U謴_^][U蜴D$L$ ;t_^]+[_^]3[S\$Ul$Vs EW=$tNQjjj~F jV豙T$8D$4K$RPUQ](_^][Ã~ST$ D$K$RPUQ5_^][Ë>+~(T$ D$K$RPUQ _^][Ë;VtjjS ;Fu~ u0VQVRF F ~_^][ËD$ L$S$PQUR蓰_^][Ë~_^][jSD$(L$$S$PQURcS _^][ËD$ 0{ _^][Ë\$ C xW~VWT t%_^]C [ËL$ T$C$QRUP_^][ÍIЛ 5`"לQVt$t^FS\$W|$ tjWjSjVЃ~9D$L$V WPQjSRF 3FtjWjSjVЃ_[^̡*PRuh*PC[h`-j7[̸F̋D$ L$;tT$RPQV[ +zaˢPPPʫPPPP莢P裫P}ȫPrPghx hhGCjhx hhG/jDP1h} hhG jh} hhGiP)Ph| hhGih| hhGi֡P@8P PBPGPPPPPh u hhhGgh u hh`Ggh u hhTGgh u hhHGwg@oPyDPn虶Pc讶PXöPMXPBͶP7RP,P!hX hh@GfhX hh8GfĶP@薶PPPP誶PPPhTX hh0GzfhTX hh(Gff!PkP`KPU@]PGrP<P1|P&聿PPhW hh GehW hhGe蓖P舖PͩP蒩P@蔩P蹪P^P胩PhL> hh GiehL> hhGUe蠩PZePOjPD_P9P.YP#@h$> hhFdh$> hhFdP踩P轩P肪PP謩Ph= hhFdh= hhF~dH;PPh$ hhHFdh$ hhG2dPPPh0z hhGchz hhxt cDPKht hhy cht hhGcht hhGcPPPhPt hhGjc@hPt hhGScP#PxP}PP ̋D$@̋D$A̋D$D$A̋D$A̋D$@X̋D$u"hhHhhjRË@̋D$L$ H̋L$D$!H̋D$@#D$̋D$L$ H\̋L$D$!H\̋D$@\#D$SUVW39|$tUl$Ep vh(HjbhHt L$V]SQ貁 ;t_^][Å~VS U0R _^][S\$ 3t4VW|$p vh~~~ F~~0F4B|D$x xp _^Vt$u3^ËF P~N hQIV RyF F F^̸Mv\FVD$FD$G@SIيʊ\$\$\$\$\$\$uڈL$VT$NV[Y̋D$SX CHUk Jv][jPU{ tnUBM VWPQ.UBM PQD8P~MMyt8EH j4htHU| _^tjD8PU| uL$ jQϜ]3[ËUB]C0C4[̸HvLl3ĉD$DSUV^ C P+Kk;ʉt$ }^][L$D3hLHWjPUzz t[EHSQM D8PQLUzu -EHKj4htHU{tjT$RU{ u$t$jV_^]3[L$D3KHËEhs͍T$t8r;ustC:+u1v4Fz+u v#Fz+uvFJ+3K3k;u*͉s4;t+PT8RC8P   K) ssL$T_^][3̸KHVs WN8V9PV<r];u3st*:]uvY:]u vA:Et FL:N VF>F0L$P_^][3̸jID̸&I|$ $u3YUl$ Vu }$} S\$W~0t`>+~;~FT$WL08QR:I~F|$|$( +9u+N F3+~tPD18PN8Q   >~0tS+PE$T18RPΘ ~4~4u t<~4u Ut)~~CjU;UeD$ _[^]YjU _[^3]Y^3]Y̸GD$Ul$ Vu D$4}$*}  ~4tU5 SWjU蠗>+~~0t0~*FU$WL08QR芘؃ ^+~0uҋ3F0;Nu F\$|$ 8v+WL08SQ{G>)|$,߃ \$=r tF|$ GjUUD$ _[^]YUjU֖ uF_[^]YjU謖_[^3]Y^3]YS\$Ul$Vs EWow'$3FFF ~FF0~4L$ T$C$QRUP蹙_^][Ã~~؃~0tҋ>+~ǃ~0u u_^]3[Ã~0t F0Iu~F~jSϕL$(T$$C$QRUP;S_^][Ë~_^][ËL$ jQVs t{ _^][Ã{ tVD$ _^][3_^][ÍIz7̳ Ab̸XDl3ĉD$TW|$`WjjD$jPEu_L$T3DXVu(jNhHjAjojD^3_L$T3^DXËL$Q_PV) u9jThHjvjojPDT$RD$$jPP1L$,QhHj.G,NV B$t,WVЃuj_hHh^_L$T3CXjehHhjojCVL$`^_33CXVZuj|hHjAjqjC3^ËD$ L$A t\@(tDQVЃuhhHhEN IB$ARP#^hhHh hhHjvjqj CV3^̋D$t4thhHjujpjB3ËD$H ËD$̋D$HL$-T$BD$p0T$BD$'L$QT$'L$QT$'D$L$PQn-̋D$L$T$ PD$ QL$ RPQ1̋D$L$T$ PD$ QL$ RPQ3̋D$L$T$ PD$ QL$ RPQ1̋D$jPËL$T$+uA+B̋D$T$+uA+B̃=uhmhhtJjj uhhtJjAhjA3ËT$L$PT$L$ P HL$PRHp̋D$Vt PD$t P詷L$T$QPVRj.^̸@D$u3ËL$D$ $t%$RP tPPuhjjL$ hHQYtL$ tPL$$tP L$(t@áhP!P̸dV?l3ĉD$`D$xS\$pUl$|Vt$tL$QT$D$RD$PVZPjughhtJjyjtjH?ujPL$ h Q萌 VT$ jPR, D$PhHj B ^]3[L$`3>dWu3$uÍP@u+‹D$u_3D$3$T$QPVUWSRT$4hhtJjxjtj>_^]3[L$`3M>dPTPMuhhtJhjtj<>_^]3[L$`3>dPNTPVhhtJhjtj=_^]3[L$`3=dËL$p_^][3̸=d̸f=l3ĉ$$$$S$V$D$WD$(3PL$(T$|$k;>9~vNL$RD$ PWr ;u/jahJjrjuj=_^3[$3<ËF;u D$ PAD$UhL$$;t$uÍP@u+‹T$jRD$4Pj WL$0SQ7l T$$RD$0UPl V[rjL$\QT$8R ll$UE}3$]_^[3;Ë\$;~Xd$jD$0UPi 3WL$XQT$4Rk jD$XPL$4Q|k F;|t$(V貓@~hJhhJ^ V荓PT$\R$P;V4 ~hJhhJ] V PV L$l+QT$LRO;$PD$(L$TQ$RjVPv$tCL$Tj@Q$j@R݌D$TjPьL$DQjt$L$,Qjsj[p̸06:l3ĉ$,$<S$8V$XW$TWD$(|$$D$SD$}_^3[$,3:0ÍL$(UQ $`ƉD$u $H&$HuÍPI@u+‰$Hƅu/L$,Q0$<]_^[390ËD$t$ ;D$jT$ȋЈD$$LWPL$!L$8SQT$*h $PD$(RPL$4QF jT$RD$4P* j$QT$4R V$PU9$` ~PHD$T$ j$QR$TPQSW ~$+͋0@u|$$l$uD$D$+D$D$,P 3̋D$L$PQ聶T$L$PD$RT$PD$QRP ̸\7l3ĉD$XD$dS\$pUVW|$p3W|$$D$t$3uhhKh~W@vhKhhKZ C;:CHL$$PT$(Rjo u hWPFtP<;thhKj{F t PGRjL$ QjPjuhhKj}T$R MPԨD$uh#hKj}8th)hKj~j@xFPe;T$L$,QL$ URP$SWPQ$tA$L$ RjD$0PjjQqD$hhKjrhj06T$(UR"VnL$tD$ _^][35\̋D$SUV33W89p@HL$ PT$$RUm u hQPEthhKj|VPPPKPe uhhKjk\$,|$SjjjPWptpNQRW}hhKjzBD$(L$$SPBT$ QL$(PQRWV"m_^][hhKjrjvj4Vl_^][øpf4L$tD$$L$t%T$RPc|PP0ph3 jjL$ h/QMtu3pVWhh0Kjl]3 ;u_3^jlWVH4D$L$ ~~ ~~~~~ ~$~(~,~0~4~8~<~@~D~H~L~P~T~X~\~`~d~h_N^̋D$L$ tD$tI̋D$PL$QP Q PQPQPQPQP Q P$Q$P(Q(P,Q,P0Q0P4Q4P8Q8P1^VW|$ phS\$LKÐ:utP:Quu3D$uNt&PɢtPjjhjW[_^hh0Khhj0[_3^PSWփ [_^hh0Khhj^0_^̋D$L$T$ H P$̋D$@ ̋D$L$A̋D$@̋D$L$A ̋D$L$A̋D$L$T$ HP̋D$L$T$ HP ̋D$L$T$ H$P(̋D$L$T$ H,P0̋D$L$T$ HF^F F;thh0Kj jSP3F;tV׃V_^]3[_^][S\$ Ul$ tEE t>V0Et؅t3Su1hh0Kj&hj-^]3[]3[VR.WVt S/'uhh0Kh5hh0Kj(,V3 ;u/;t Shh0KjAhj,_^]3[hh0Kj njU^>FF FOFtV׃V_^]3[_^][̋D$L$P3pVt$t5x t/Ft,P uh<h0Kj&hj+3^Wh@h0Kj(U NOFthJh0Kj jPNVWF thOh0Kj jPNF G GGNOB VWЃ~_^W_3^Vt$t4t.x(t(F@$u^VЃ)F^jXhTKhhj*^Vt$x(~t jphTKhhja*^@S\$W|$t@FP0u ˉG_[^9s!jshTKhhj*_[3^ËD$ L$R(PQSWV҃_[^jkhTKhhj)^Vt$t4t.x0t(F@,u^VЃ)F^j}hTKhhjk)^̋L$t;t5@0t.yt"hhTKhhj*)ÉL$hhTKhhj)Vt$t4t.x8t(F @4u^VЃ,F^hhTKhhj(^Vt$x8~ t#hhTKhhj>(^@S\$W|$tCFP u ˉG_[^9s$hhTKhhj'_[3^ËD$ L$R8PQSWV҃_[^hhTKhhj'^Vt$t4t.xPt(F@Lu^VЃ,F^hhTKhhjH'^Vt$xP~t hhTKhjij&^@S\$W|$t@FP轭u ˉG_[^9s!hhTKhjij&_[3^ËD$ L$RPPQSWV҃_[^hhTKhjijc&^Vt$t4t.xXt(F@Tu^VЃ,F^hhTKhhj%^Vt$xX~t hhTKhjhj%^@S\$W|$t@FPmu ˉG_[^9s!hhTKhjhjO%_[3^ËD$ L$RXPQSWV҃_[^hhTKhjhj%^Vt$t4t.x`t(F@\u^VЃ,F^hhTKhhj$^Vt$G=x`uxPu xX'@dNt3t+t#h)hTKhhj"$^W|$WjjVЃ~tFuh7hTKhA;th>hTKje-W u5NWQu$hKhTKhhj#_^ËF t P貱Wj~ BdjVЃ _F ^h[hTKj jWF_^h#hTKhhj!#^Vt$x`~t#hjhTKhhj"^@S\$W|$tCFP蚩u ˉG_[^9s$hmhTKhhjy"_[3^ËB`SWVЃ _[^hehTKhhjD"^Vt$t4t.xt(F@u^VЃ)F^jIhlKhhj!^W|$twtqxtkt jahlKhhj!_Vt$u^_Ã>u\PQWҋP莯^_j[hlKhhj8!_Vt$t4t.x t(F@u^VЃ)F^jzhlKhhj ^W|$tzttx tnt#hhlKhhj _Vt$u^_Ã>uIP QWҋP{^_hhlKhhj" _̋D$L$A̋D$ @H T$H T$QP@Ѓ̋D$L$H@̋D$uD$@$Å|L$;A$I 3̸&D$ L$VPQD$ >u^YV,~+T$D$RPjjjV~L$QV]VD$^Y̸~SUl$uUWFtJuLD$PWة~L$Q4P豐؃u!jThKhhj]3[YÃ|$Ft3JDtVPу~܋F@@P3]3[YËI} ( t&T$QR4HD$T$X3T$Rȃ$I;|$ ~5D$,;t U?hG hKPD$,> td$L$hQOp3.FuT$XD$L$(t?<;|$PN~I.ˀN@]@ˀ .FuƉD$T$,;t UJ?D$t PD$[^_]L$438j}hKhjdj D$,;t U>D$t P8[^_3]L$43d8hhKhhhKhhhKjkjmhKjzjdj >L$X[^_]33 8̋D$ L$T$jPQR.̸Xl3ĉD$TUl$`VW|$ll$ t$SjWjPP.؃O~ChkhKU < u[_^]L$T3`XjWUVb.l$ #j hKU:c [_^]L$T3(XSVUcL$ ;t V{=[_^]L$T3Xjh UbL$l _^]3Xh_hKjO;3Ƀ ;uhbhKjAj{j 3ÉH HHH@Vt$teFt,t P<Ft P<FFtFt P<FF Ft V<^øT$ D$(L$,T$$D$L$L$$$RD$ L$D$ 3S\$ Ul$W33;~J<u ;tWtR@A;|D$V;t 0;tFurh_hKj9 ;uChbhKjAj{j q^_]3[h,hKhhj L_]3[Éx xx8x@~3F;t9n }oF ;t W\;ŅuhChKP^9 u7hUhKjAhj D$(t90t V^_]3[ÃNUSWD$ ݉~n Ft0D$^_][̸ L$Vt$QT$RD$ D$ PL$QT$(R1yf |$t&thhKPhj 3^ ËD$T$PL$QR tL$^ .̋T$u3SW:~xZ tmJD98uOHD9uPtGt<t1t& t@t$ۃ3Ul$GD$t-VuBWPFV? ~ VD$u^]_[SUVW|$3}dD$t0uj.tyD$(EN D$ ׃EOF ~shhKW6؃ u?AhhKPhj _ tD$t90t V._^]3[WUSb L$( D;3ۋF>t P`8D$^Ft0L$_^)][SUl$Vt$ƙW+θ؉D$Ӆul$ŋt$tqf O;| ~FuhhKQ5 hhKQRP6u"hhKjAhj . _^]3[Ë+A~QjPB  GD$nV": : ؈>~N|uH_^][ËL$Vt$ ƙWt/P9|(yt!+κ_^и_3^̋T$VtCrt<3ɸ~4Ul$W|$t;}9 A;|_]^ø^̋D$xt3SVWx3 3u 8Ztz+tu-tp 809@0;809@;Í LJ; K; LFy 8Zu@3;_^[À+t-u@H;T3 80|J9ET8@00|590ҍ LJ;K|;L@|3;_^[_^3[̸ SW|$ D$ PI@u+‹؍D$P\$ |$t2Vt$ tSWV) u^_[F^_[_3[̸$ S\$,ujF*؃u[$VD$PL$8QRD$8L$ut;t>{uKPQW! #_^[ËRjW! u_^3[Ë3CUo85VrhMhMUNK VQUO ]_^[̸T$Vp@u+ƉD$D$PT$D$D$ ^u $QD$8u3ËD$t$RP%t̸$vD$, $QT$0RD$4pJu!jshLhhj 3$Ë@2|!=}D$,L$(jjPQ$ËT$,D$(jjRPl$̋D$L$QVp;t 3^DQP}!t^SVW|$32ۅWUou D$AL$u ~-2$=u ;~<u@;|t$T$u D$]_^[Ë tA7uD$]_^[ËGuVPQxT$$D$ ]_^[À|0D0L1u HIN8tÈNIH~ ӈNIHD$]_^[_^3[̸UVt$t.uju^]ED$SW|$$hW ;hMRL$ ( D$u:hhMjAhj ptt9.t U_[^3]Åu EPE;utCO|;T$D;L:utHIN8tu@:Gt$Et P4)D$E}t.L$T$ _[^ʼn ]ʈNIH~҈NIHE;utCOWSP ̸ Ul$Vtuuj>u^] FD$T$ WRD$PL$$L$QT$RD$,Pyf1|$ts#L$ h1AhMQN& u>AhIhMPhj tt9ut V_^3] FD$ t+L$9ut AHL$D$ PQWT$ T$Ft P'~D$ tuL$T$ _^ ] ̸ l3ĉD$Vt$>F}2Ft P='h[hMjI% Ft3ɉH~u*h`hMjAjvj 3^L$3| ËL$} F3It L@r3ɃxS$\VAy[L$ ^3̸ ̋L$W33u_ËQuVqu^3_Ãt_3Ʌ~SA ;|[t^_S\$ VWujuhhMj:[|$G %WFt @9}LNhhMPQ{$u.hhMjAhj <;t Vo_^3[ÉFVRWYu F_^[̋D$VW|$ WPQR9 uhhMjijwj _^Áu jV_^+̋T$VW33L$ SJtrAa|z~UA|Z~K tF0|9~<'t7(t2)t-+t(,t#-t.t/t:t=t ?tyu[t_^øu_^Vt$~t3^W>%yH@u-N3~ Q<uzu:u ;|;}_3^ø;~IVA;|PFPF_^̋D$xu8t3Ë̋D$xtL$jQzD$T$uD$ L$%AËT$ D$PVt$W|$tWtRVu)Bu_3^PD$jPy _^t׋L$ PWQV _^ËD$ D$xtT$jRD$8uL$_q^ËT$_r^̋L$tAD$t9;u3t+t@D$IL$PT$AD$3Ã̸6SVt$3ۅu^3[UWV l$0xjWVPՃ؃y|$0WSjvL$4 D$L$4QWST$0jRD$8|$8iV薼WD$$j{h0MVD$uP6؃ uj~V3N~9$L$$T$$RWV =PՋD$,+VDG ;|΋D$$L$(+D$h0jV|$(PSt hh0MW|$u%hh0MjAhj _]^3[V|$(3蔻~/{GL$$RPQT$0VEi;|؋|$D$L$PWQWSD$(_]^[V3+~$d$T$$RWV$PVG ;|D$$L$(D$_]^[̸,D$0SUVWtt؋l$Dt$HML$u433؅uhh0MjAhj _^]3[,Í1D$,+PD$(PL$(QT$4RD$ P8D$FL$X;L$$t hh0Mjehj T$T;T$ t hh0Mjhhj ]L$(|$9;T$,v#hh0Mhhj )!u M+ΉL$(9T$,;sat$LL$(D$u 3QD$P@L$0|$D$u(QL$QPփ t/PSVtL|$;|$,rD$@t}_^][,hh0Mjqhj vET$$+RPft1D$@t9t%D$PtPST_^]3[,S衸_^]3[,̸W|$u3_YS\$VjWjK hHMP]ujMhHMjAjoj ^[3_YÍD$PWt$$PL$Qjt$ T$,V^[_Y̸6D$ $uYVt$ VL$QP褉L$ ujhhHMjAhj D3^YVPT$RjL$ D$Pn^Y̸4SV3t$ 3G;D$;u!hh`MjAjkj ^[4UW$+w\+>;PD$PJ<L$QD$HWRP@ } m~ ;sL$y+RD$0PL$0QT$;l$PU;t|v%$EL$HWPQO? ~j+u|$0L$l$;rm؅C?hh`MhFh2hh`MjA+hh`MjAhh`MhhhD$L_(]^[4̸&L$VWD$PQD$3K|$|L$ WPD$PQT$T$$ t W8_^øL$VWD$PQD$3|$|!WL$QPD$$T$T$RP贝t WU8_^VRP4Duhh`Mjhj 3^ËD$ WPjjjV@L$$T$QVRL$$T$QVR"V*: _^VOPdAujh|Mjhj 3^ËD$ WPjjjV=L$$T$QVRV9 _^̸ l3ĉD$Vt$>F }/Ft PjQhMj Ft3ɉH~u'jVhMjAjpj 3^L$3 ËL$} F 3t L@r3ɃxS\VAy[L$ ^3̸| ̋L$W33u_ËQ uVqu^3_à t_3Ʌ~SA ;|[t^_S\$ VWuj  uhhMj:[|$G % WFt @9}LNhhMPQu.hhMjAhj ;t V _^3[ÉFVRW_^[̋D$VW|$ WPQR uhhMjijqj +_^Á u jVr_^Vt$ 3^ËT$ xT$Ƀ ^Ê$ɋ?  P@@?? ʁ&T$ ^Ê$<Br$<B$<B$<R:ɋ? P@? P@@?? ʁ T$ ^Ê$<3Br$<5B$<(B$<B$<R:ɋ? P@? P@? P@@?? ʁT$ ^ø^̋L$uQD$ =stËT$=s#|t$? A=s1|ƅt" ?Aʀ$? A= s@|t1 ?ʀQA?Aʀ$? A=sSCt@?ʀQA ?ʀQA?Aʀ$? AÃtO?ʀQA?ʀQA ?ʀQA?Aʀ$? A̸,VSUVW3D$$P3|$|$|$|$ 43ۋt$D;tt$H;to|$XquNQln+Ft8tPR:FvRGP9h 3Cwt$PW|$DVhhMPD$,F \$hSihhMPD$4D$@" $D$L$ QVl$(׋T$`3WRD$4P}L$QT$(UR tmS\$D$PL$,SQetQt$LF;t P~ F T$^|$F WhhMh7hhMh&hhM|$jhhMD$jAhj L$$QtT$RU3U t$tD$PV3V D$_^][,̸SUVt$<3WVl$l$l$$؋FP\$,;9;F;>O Ah\$0;T$8L$4RT$@QL$4SRQVЋuYT$8D$݋D$@P D$tSP2L$Q tT$ RU2U D$_^][ÅhhMjhj m~3L$$A t9G ;tRQPWPD$ P uhhMhNIL$W B$NtL$jVQPSB\$4tT$jVRjPS D$,T$sD$ hhMjAhj 'hhMhhj PPLu#hhMhhj zD$PcL$LQ ;t#hhMhhj ?QjWD$(jP臼hPWPT$$R uh6D$WP+L$Q6D$L@RPL$0Q豽hhMjhj 3]T$[R _^$̸&Ul$ VWIu FD$ O{uFD$  FD$ Yu6D$ VF ‰D$ NF FD$  FD$ D$ PWV |-+D$ tL$QPӃ~ W_^]Y_^]Y̋D$̋D$Pjj2L$ ̋D$T$̋T$D$SQ[̋L$Vt$ @@H^̋D$Vt$ PhQ ^̋D$v3Ãa|z~,A|Z~"0|9~ tPhNh tǸSVt$ W|$tVutvt vtvu_^[É_^[̸@l3ĉD$_^̸&D$$u3YPD$PtL$ Vt$WhPQV{YhPV>M_^Y̋L$ S\$ VWhPQT$RjD$$ptVhPVL u_^3[WIWNt|$D$t QI7_^[W|$u3_V]Hu hhPjAhj _^3_WVMD$PVVmN^_̋L$ S\$ VWhPQT$RjD$$otVhPVL u_^3[W^HWNt|$D$t Q7_^[W|$u3_VmGu h,hPjAhj o^3_WVLD$PVV}M^_̋L$ S\$ VWhPQT$RjD$$ntVhPVK u_^3[WGWMt|$D$t Q١7_^[W|$u3_V}Fu hRhPjAhj ^3_WV LD$PVVL^_̋D$L$ T$Vt$PQRPu^W|$t0NAt PbVL$ zFF` vN _^̋L$D$tL$tPRHL$ L$t̸ Q̋D$ L$T$h QPQRWm̋D$L$h QPQU h QE̋D$h QPAĨ|$D$V0uFu^ø^̸R̋D$ L$T$hRPQRl̋D$L$hRPQT hRD̋D$hRPH̸pR̋D$ L$T$hpRPQR'l̋D$L$hpRPQlT hpRvD̋D$hpRPH̋D$PhpRQ̸R̸,S̋D$ L$T$h,SPQRwk̋D$L$h,SPQS h,SC̋D$h,SPaG̋D$Ph,SVWh,S3rCtUD$ P~҂FtutNWQvu h,SVFt Wu_3^ËT$D$RPW _^̸PS̸lSkL$3҅‰Vt$t)L$ APtu^ū^̋D$V0u^WV D$tt@PVVڪƒ_^Vt$>u衫L$ PD$PQ u5t+T$BPt谪3^3^ø^̸S̸S̋D$HT$ ̋D$HT$ ̋D$L$W8;yu_SUV}+S腩t$ht0t ʈFE|I0}҈0y^)][_W|$~"hhShhj K3_UVt$t t333~ d$t 00@ ;|^]t+L$;Auh놋T$_̋D$T$QhSRM ̸tT̋D$ L$T$htTPQRgg̋D$L$htTPQO htT?̋D$htTPQC̋D$PhtT̸T̸ ŰD$ L$T$h UPQRf̋D$L$h UPQN h U?̋D$h UPB̋D$Ph UVhh(Uj t ~t Fu;hh(UjAhj tt Ps|VJ3^ËL$F FF1^W|$t@V7t8FPGhBQ~F t PV^_{̋D$hBPq~̸ SU3W\$ \$}D$ ;P{~]SQ{9ot"|D$t_T$ PRztMoD$WPpzt8QC`{;|jjhTT$jRFFWPhu4D$ hDP}h"h(UjAhj j_][ ËNQjjhTD$ PL$QT$({FT$ hDR<}_]F[ ̋D$HT$ D$QRT$ QR3ɃIWGP4LV)uL$WQ_S\$ VsWVC u^[3_Ë6U~#d$x RӃt MF |.~IxPӃtMOD$x3ۅ~Y$xCQ t% GIFFCx%R uP GFC;|D$+xL$]^[9_̸VSUl$VW335y~6VW7yjjhTD$ D$ UPD|WFx;|ʋ^][YW|$t=D$ t59t(VPh Uth UP)>7^39_3_̸覱C U3l$ D$l$;t P&k Phxu k]Wy|$; VQ7xUR3xD$9Ft.PyD$L$ PQvVT$htT9POQNE tjT$WRvtXPEw;l|$ 3UNLQ5^v(t>V_^3VRVj ~ ~~(F ~8~<~d~D _^̸V̋D$ L$T$hVPQR\̋D$L$hVPQE hV&5̋D$hVP8̋D$PhV̋D$L$T$ PD$ QL$ RPQj ̋T$T$L$L$D$SUl$Vt$WhVUVP[t&+t)UOdVQw uhVW7_^]3[Ë_^][S\$ VW|$hVSWC tGdSPF_^[̸W̋D$ L$T$hWPQRG[̋D$L$hWPQC hW3̋D$hWP17Vt$W|$u)tFdt@tP`Fdx_^Åt!~duhW%3Fdtvdu_3^Ã~u `FtL$VQWR~ _^Vt$W|$u)tFdt@ tPJ_Fdx _^Åt!~duhW2Fdtvdu_3^Ã~ u ^F tL$V QWR _^̋T$Bdt@tL$tJdQB3̋T$Bdt@ tL$tJdQ B3̋D$WPEu_Vt$ t1~duhW1Fdtvdt>u&qu^3_ËWQn^_̋D$WPu_Vt$ t3~duhWQ1Fdtvdt~upFu^3_ËNWQ_n^_Vt$Fdt8thpPqNd^Vt$Fdt@thpPrqFd@^̸X̋D$ L$T$hXPQRX̋D$L$hXPQL@ hXV0̋D$hXP3̸X̸|Y̸ VUVpW3Vt$l$.n~= It$UV%njL$QhVau|$ tBK_^] Ã{@|$uoC@S@WRlD$jL$QhVF uf9D$ uFvVD$pmL$;}YIQVimx~R=u+D$ V4mL$;|WWFhZ뒁KD$PEm;_^] _^3] ̋D$HH39V~ H~~BH~~BH~H~~H ~ t1H@N 9~ IP N 9~ IQ P ` HQR1̸Y̋D$ L$T$hXPQRgŰD$L$hXPQ= hX-̋D$hXPQ1̋D$ L$T$h|YPQRT̋D$L$h|YPQ<= h|YF-̋D$h|YP0̋D$ L$T$hYPQRT̋D$L$hYPQ< hY,̋D$hYPq0̋D$PhY豲̋D$T$D$T$̋D$V0~uhU)hFFtL$ QPit F$^hzhZjAhj 踣3^̋L$AD@tL$3̋L$AD@ tT$ jRT$RQЃ3S\$VsD~ t+W|$WGPW PN PD$PSу_^[^3[̋D$PD$P@QRPh|Y2̋G Sڅu!u[ËHQSG@[ÅuZVP3Si~4G VPRi8uHQSGtW RFi;|^3[^[̸D$$SVt$$D$QRmiu4hhZjj HQihhZjj $HT$RQj؃}^3[ËBUWPth;}Fl$8QSRmhD$<PQnu ՋuBPC.h;|_]^3[ËD$0t83_]^[@̋D$80$0t80hhZj uËL$T$HL$ PT$H P̋D$t D$>̋D$L$AH̋D$t@t|$uhUPd̋D$SD$yUVWPK,QPSFjjhS' Ct SjjjZSjjjXSCjjhSC$0C(t {$uKjU3f~MWUfP =YuK~UG[f;|=t=tK_^]tKDASЃ3[ËSDBt SЃtCt PJCt P(C$PRK(QRS@hR R-h[Ë 803CCCCC KDCHC@C$C([jEh Zj,B3Ƀ ;ujHh ZjAhj 贞3ÉH H H$@(HHVt$tcj]h ZjF(jPHt PFt PFt P~F$t PVw^̸Z̋D$ L$T$hZPQRM̋D$L$hZPQ6 hZ&&̋D$hZP)̸Z̋D$ L$T$hZPQRWM̋D$L$hZPQ5 hZ%̋D$hZPA)̃|$uD$V0jO諲^̸t[̋D$ L$T$ht[PQRL̋D$L$ht[PQ4 ht[$̋D$ht[P(̸[̋D$ L$T$h[PQR'L̋D$L$h[PQl4 h[v$̋D$h[P(VW|$t7u(#ujTh[jhj _3^ËD$ PVm(uj\h[jVtYtt6=thh[h`L$T$QRFP:| uoj{;L$T$QRFP uQjqL$T$QRjP Fu2jgh[j hj tt97t V)_3^Åt7_^Ul$ VtCutzAD$邻AD$Ɖ̋T$B tnt;jhDOSm u>t!Fh h]jjuj ht$$L$Q蠵_^][̋L$Au L$u L$T$jhD^R 3̸ 覉SVW|$$3D$D$ D$u D$ D$ ;uD$D$(\$ t$T$ u0j hh_Vu j hx]V] D$(u(Q1P@Ph hL_VnrD$(Ujh4_V MS5}S\$pUh CPh Sh_WD$+Q3QK~R|$uhDOW8D$jUR3KPD$jPPcL$$QWREJ;|hX WSh_W\~h CPh Sh_WD$+0NQ3J~T|$uhDOWD$VjURJPD$jPP趟L$$QW[VREQJ;|hX W?Sh_WFt@Ph Sh_W~ tZh Sh_WuF 3ۃ9~- u PPQhx_WGF C;|jhX W ][L$\_^3̸؂XSUVt$Wh`V|$ Q蟇P@Ph h`VWPOjQVBjjP,Sh h`VLSʭh h`VQ RVh h`Vn@$t PV h`VNhX V@QjjRhx`V;hUH ~h``hD`VU3|H~jISUyHh0`VQVOh`VWRV^hX VGjjPh_VDUCH;||$OWQRV= _^][V:PujKhajhj &3^ËD$WPjjjV_L$ QVV<_^W|$uG_à Vn u D$S\$hPS u[^_Ãu L$Qh8aS 3҅[^_UWq*L$PVPVQh$aSx][^3_Ël$ E>-_t T$PRhaS>uVWIvtG3+ʼnD$I‹+ȋ+u,hX SU~aD$$hPS tGL$.;Ϲ t QRh S~F;|jhX S4 ][^3_][^_S\$UVWhaS=t$ P; ua PǕPhaSRλuh|aSjjWSzW @8tHQhdaS VP躙ua PFPhHaSF8h 3~_+ʼnD$98 ɋ+ujh@aS L$.;Ϲ t QRh SF;|jhX S _^][̋D$SVW|$h PhaWt$(>t?Ul$NQUqt uhDOWRW2ۃ >u]hX W_^[̋D$xSVpWts\$GI:utP:Quu3tCˍI:utP:Quu3t wu_^[Ë_^[̋D$L$PQQ}3ËL$tT$ RPQo tVt$ t%Ft@t L$VQЃ^À>tFH w|~$~j貑L$ ^ËVD$^ËL$^hehaj@ u^ËL$@39^P蕜>utH @L$39^Ë/~~~}e~̋D$t'HtItPRуÀ8t xu@̸zSUVF3;t@;t؉\$ l$ 9l$u/w$$F;t@;tVWЃ^][YËv;t;tЉ;ۋF;t PWBVW);tUVWUӃ;t9l$u.FhhaPģ ; NQUPpz VjW* ;fUVWjӃ^][Y;tUVWUӃ;,9l$u=VhhaRB ;NQUPyVUW2*VW{* 9n ^~SW+SPBtNE;n |D$ jVWjЃhhajdjyj NyVWw^]3[YhhajAjyj (y^]3[YËp[4D$wZd$$xHt,u:AvËHt%I tPVуÉD$KD$@Ð'pppDep̋L$W|$j@_Vt$ FЋt2tL$^ËVҋt$P^tD$^t5?uh%hajAhj w3^ËL$^W|$ R_^̸FwL$Wj|$D$^3Ʌ_I# $Y̋T$VtBt@ t^T$D$q:t$uBt>tn wO|$hR\e^ÅtB^^jVvQ ^ËR^Ë2^ M̸&vFt ?St Xt\$ D$\$ɃrU$XFtPW][VW][ÅtjVWjӃ*VW$&;F N,UW(UP)@][L$@VWЃ][VjW% tjVWjӃVWN&F NlD$ ~:jUW'؃ tSWW'SPpD$ @;F D$ |̋\$t jVWjӃ|$uR][ÍI _̸6tVt$WteD$SU(U3 ;~5t$SU;NjD$ы|$UC:;|U:T$][_^Y%PFЋ|$_^YVt$ Wj|$__^Vt$ W|$ j?_^̸$VsT$0 D$4VWL$ t"t _^$Ër%t$D$ 6t|$@D$t$%D$ D$t$D$ D$ |$@?U|$Dt uSgT$83;~tD$tD$|$tu t$ D$$39|$|$$D$ S3F9~;VSH9L$PT$HQD$0BjPL$8jQSF 9;|ŋT$ RWU蘑L$4 D$0L$(tL$QPUx t$T$D$RPVUSL$TQWjPD$DSPfu S8D$[]_^$ËJ PVыT$DPD$DRP0[]_^$̋D$L$SYVWx;| Ur;ustC)+u1v4Bi+u v#Bi+uvBI+3]u+_^[̋T$Bt@tL$ RT$ QL$ RQЃÊL$uzt 9uVW<u @|$9ru |$D$ yHwy$( Aq 33t9rtt z~ _^ÃztȈL$D$XT$ ҍD$#RQ`_^-tPtKz uA tD$t A_^ËA1L$tt VPQt!VNnFT$V l$T$L$H}SD$PL$QT$$RD$XP芆l$,tTL$T$NL$HV +׉FnVu2;~,hhbhjhj c_^]3[ ËL$Hy)hhbjfjhj ct_^]3[ ËT$<|;T$uoT$@;T$uett+t$,tЀT$0t$ D$ t(D$(tT$D$$tT$D$4_^][ À|$Dt _^][ Åth'hbhjhj b_^]3[ ̸ VbS\$Ul$u]3[ ËW|$ ?S|$Q%PFPRL$$QT$4RD$+PjL$8jQ|$<,uh3Cu _] [ À|$uh;hbjx'S\$jVST$ RUu$hChbj:hj a_]3[ +|$߀|$t"SL$&uChNhbht.hYhbjwhj aVU_]3[ ËD$ L$_][ VRT$0RU)_][ ̸`|$D$V0Wu0_^SU~t|>u~uKWD$PL$$QT$ RD$ Pމt$$JxTL$t+t$$tET$4 +tbhlhbhhj |`][_3^hhbjfjhj Z`hahbj:hj B`(][_3^ËD$$][0_^̸_d$(S\$ Vt$(D$u8\$0uL$,^C[Ul$0WD$$|8u x(UT$ RD$4D$ PL$ QT$QS詪T$CVRP _D$ ƉD$L$$+|$8hhbhjjj ^_]^3[Ã|$8D$hhbhjjj f^_]^3[hhbjfjhj D^hhbj:jjj ,^_]^3[h'hbhhhbjAhj ]_]^3[hhbhjjj ]_]^3[ËL$0_]^[̸V]L$ T$Vt$,D$PQRT$42D$ ^̸ ]|$$Ul$0VD$ u h hbj}jlj =]^3] ËD$88SuރX\$W|"hhbjjlj \_[^3] À|$Ht"h%hbj~jlj \_[^3] ËL$L|$8QjjjUT$(RjD$0jD$3PL$hbj:T$8w3;o D$}1VS L$XQT$ RT$LPu*E;o |;o uI|$Lt.WSJ_^][ ÅhShbt$,j:0hbhbhWUS7D$ L$DD$, tjWSjЃ_^][ ËT$8T$It7At1T$AT$u BËI juhbQRPxr3̋D$t2t,D$@t!@t@t@@̋D$tCt=D$@t2@t,Vpt#t P zFF^̋D$VttD$@t @tpu^Ët PyW|$hhbWw u_^ËL$WQPdN ~_F^̋D$ VtYtSD$@tH@tBpt;~u5W|$tNQRP NN D$ _tV^3^̋D$tD$Ë@L$Vt$ u^ËFWЋL$ Gu Gt?_^t RhPRwW 3Ʌ~ 9t6A;|Gu$|$thhbhjnj M3_^_B^̸d̋D$ L$T$hdPQR̋D$L$hdPQ hd̋D$hdP̸d̋D$ L$T$hdPQR'̋D$L$hdPQl hdv̋D$hdP̸d̋D$ L$T$hdPQR̋D$L$hdPQ hd̋D$hdP̸e̋D$ L$T$hePQR'̋D$L$hePQl hev̋D$heP̸ e̋D$ L$T$h ePQR̋D$L$h ePQ h e̋D$h eP̸T$(t$6uWETD$(t W1T3uh,hS躐3Ʌ_^][YÅt(PS蝐>h S臐(`$@D$uL$APSiVSVSVS uT$:hD$ PD$OhX SL$ FjQRPSW\3D$L$(QRVSv D|$thX S膏'_^][YÿNo~̸6=Ul$Vt$(FWtxtT$(|$T$\$@D$ D$ }uIt8uL$4T$(SQL$8hhW賎_^]r$FtT$(SPRUWZD$0L$(T$4SPQVUu_^]ÅuT$4L$0SRT$0|vt4Ft-L$(Sh QUWЃHhX -D$42PhxhWN _^3]VUS|5;F }0F4VUGL$0SVQPW_^]PhXhW 3҅_^]ƒÅuD$4L$0T$(SP'|$0u|$4t6thThW_^3]hX WD$ tL$QVUjЃ#~ VD$T$$~MD$$jPUsVUJL$0D$u ~0un+ËȁyIA+‹;;D$D$ ~P|$4_uhhhVY T$D$hhhVRPZt$t$4D$3~[I3.HЃ wHwWP7L$L$ʊ F|G;|t$4|$$D$ D$D$8L$,PVQ \hhhhjfj /_^]3[hhhhhhhjAjfj `/D$$tPZ_^]3[hhhh땋L$0T$_^]Q[SW|$3ۅu_3[ËUVu&D$jhn P ^]_[3~l$$t3k#+ujhhUs uK؋G0 0 T$jT$ RUL$%6 uF;7|^]_[^]_[̸-D$$L$SUl$(VWP3UQt$t$ t$$P t$|( uH(k|( uH(W3Ҁ|(\‹P|$ ~* *0|9~a|f~ A| FJƒ( +NjȁyIA+‹3;D$D$~K|$4^uhhiVV T$hhiVR7Wl$0D$t$3~^3.HЃ wHwWP7L$L$ʊ F|G;|l$0|$ D$D$L$4T$(QUR~ }hhihjgj U,_^]3[hhihhhijAjgj ",D$$tPaW_^]3[hhih땋t$D$,L$_0^]H[̋D$L$hiPQ ̋D$hiP豷̋D$ L$T$hiPQRW̋D$L$hiPQ ̋D$hiPQ̸*l3ĉ$$$U$VT$$RD$L$D$3^u^3]$3*SWhi)hij(@O{WBG@jUiOhijWVJjD$< ?NNBFy|$ ЋHu jVWV*thhLjS0S D$u hhLjjAhj )WBD$PUl$,hhLjURD$uh뮋jh@jQ?I uh둋VBL$T$RWHGHSQ{|$uD$>jh$j$hRT$(D$t hhLjjghj (D$P@u+ƒ$ D$t[j菦L$Pj$PQR7[j jf j$$f$D$j$QjP$RjP~Pi $hPzNQBj$QjD$e~PT$L$ WD$SZQP[tL$MhiW_^]hhLjhhj #hiW˯_^3]̋D$L$ T$jPD$ QRPSW|$3ۅu_3[ËUVu&D$jhhPFt ^]_[3~l$$t3k#+ujhhUs uK؋G0 0 T$jT$ RUL$%s uF;7|^]_[^]_[̸V"L$(T$D$ SUVt$0WQ3VR|$|$ |$(D$$@ t |$| uH0| uH0v3ۀ|\3҉\$$~* 20|9~a|f~ A| FB;|ƒ0+|$t>0D$u ~0un+ËȁyIA+‹;;D$D$ ~K|$4_uhhdjVJ T$hhdjVRKt$t$4D$3~^3.HЃ wHwWP7L$L$ʊ F|G;|t$4|$$D$ D$D$8L$,PVQs ^hhdjhjej _^]3[hhdjhhhdjjAjej r D$$tPK_^]3[hhdjh땋L$0T$_^]Q[VWjph|jj4I3 ;ujph|jjAhj _3^É>YF;tj@F;t܉~ ~~~~3F F$F(F,_F0^Vt$tmhh|jjF0jPBOFt PLYFt P@F t P|Ft~t PJV}J^̸,S\$8Ul$8VW\$4D$0D$:tuuuFK3L$HD$uL$,D$,L$HQT$R!Cu NL$(D$QT$R~WD$<X u OD$T$0L$(+QD$4D$L$,PNQ u PT$0+T$T$(QV9P4P FuD$WZB8u,@~D$`7@QPN Q 3F F$F(F,T$R=uRhPD$uF(jjP tC>uN,jQW ~L>uT$D$O$RPSQ;l[_^jWh[_3^Ë$tT$D$RPSW l[_^Sk≠D$L$$RjD$D$hPL$!k̸fL$ $PjhQj~T$ $ T$L$ ̸&D$L$$RjD$D$hPL$j̸L$ $PjhQqj~T$ $ T$L$ VWhhhkj@]@3 ;u_3^hhhkj<@ F;tD$ ~ ~~~~0~8~4>FFxp _@ ^̸&|$UWl$|$$|Vw u ^_3]ËSD$B$HF jjP .N$jQW ؃ jWeWkD$ [^_]ËVRUj4+Ń ;FF~hkhhhk8 FD$NVQRUD$ jP9n}VNV G$QRP_3_̸ D$u V0FN@L$V T$NL$ NT$RPQVj ҃3^ ËFWPjQ.hhkPn<|$4D$@Ht7L$ QjjjЃ~T$ RWaD$Po; {0t't@tu,hkFh(z ?h  8hk1t$)tL|$t3hX* WSal$ hkWBaL$QC4;^][hkWa^]3[VWt= <"tP׃tFFu_3^FN_#^_^̅u3ËǍPd$@uS+Vt8;r( $<"tPӃtN;s^3[ÍN;t^[̋D$SVtAP]؃tK;t-U- W>WՃt W F>u_]3ۋD$tP\u^3[3hVhkj7 tpPD$HQ^[̋D$Vt$ t69t/ d$:utP:Quu3^^Ë39^3Ʌ+ȋ̸ F D$ $QVD$T}3 PV  ̸ VD$ $QRD$}3PFPVt$t P_8Ft PO8VF8^Ul$VWuÍP@u+‹Ѓuōp@u+ƋG;B5 jhlSփ u+WKUQփ ujT;hlRփ _^]_^3]̸ l3ĉ$UV$W$Pbu_^]$3 VU`$$yChD$PW\ PL$QV\hT$RW[thlV¡hD$PW] ~pS$3ۅ~%T$JI  u uHtPL$QV'\ tjhlV\ hT$RWp] [jjj V\^V`U@Z$$_^]3̸ ø l3ĉ$SUV$,W3lj\$ |$$l$H@u+D$T$D$eD$hD$,PS\ 3$(_^][32 Ë|$$L$W֍\$,G:u \$\$<|$3~L$(+ˊ1< u< u+|$t8D$tL$UQoePQ`jjhU]|$tjhlUwZ |$tVT$,RU`Z L$ hD$,PQ[ T$UR̋D$SUVWمtGPWu_^]3[À}t+d$>W t W F>u3t;S?W؃t;t'>W t W F>u3h9hkj 2 gh.^F_#^][Vt$t P3Ft P3FthP:Vq3^SVW|$tvD$ L$\$PQSM uj}hkjAhj _^3[ËT$WVRZjjj VZV\VV;u_^[ËD$L$T$ PQRw _^[WJP]uhhkjAhj 33_ËD$SVPW[L$(T$$QL$ D$$RPQVjjj VEZV[W)V4^[_SVt$ W|$ Wh;w"}&hhdshhj _3^ËT$+ wAP$<_^_@^_^hhdshhj L$D$L$Qh\sj _3^_^Ë)̋D$t(|$u!hhdshhj s3Vu"h hdshhj F3^ÍLF t*PQT$@D$AQ ^ËD$ T$D$QT$AQ ^SUl$ VWuōP@u+‹ q3;xuWUPӃ tF 1r_^][Ë A_^][Vt$tJj D$ PV L$ t9t T$ ;u"}"hLhdshhj 3^jPD$P, uhQhdsjAhj 3^ø^S\$UVW|$333ɋÅ~8:tA@;| p++ËSu3h/hdshhj sShsjf _^][éuAL$Aqu,<;t&h<hdshhj %_^][_^]3[w5$D$8thIhdsh뷍XP͋t_^][ÍD$P\$͋JT$:t&hhdshhj _^][Ëuh hdsh͍D_AL$T$^]P@@ [jjjjjD$0P{<_^][ËL$jjjjjQ׋T$jjjjjRjjjjj뵋= jhsV׃ uL$_^]A [jh\pV׃ uT$_^]B [jhsV׃ uD$_^]@ [jhsV׃ uL$_^]A [hwhdshF<*6̸Ul$VWu$hhdsjAhj _^3]Åu L$$A $d ?hhdshhj kVr_^3]Ãt0hhdshhj 6V=_^3]ÍNQT$RD$D$|$ o9hhdsht0hhdshhj Vǭ_^3]Wj7F hhdsht0hhdshhj aVh_^3]jWTFhhdshBt0hhdshhj V _^3](FuhhdsjAjWP uhhdsjAFL$$HVR<hhdshu u5QPUjFWPchhdsjAWhhdshhj V#_^3]BFu-hhdsjAhj V_^3]ÃucL$ QW;uhhdshVBFL$ VD$$B|$$uF` FH L$$_^]ÃujWPH Ƀu/|$$u(Phjj,WHuhhdsh?hhdshhj V _^3]h.hdshhj Whsj V˪_^3]ÍI0 y! ̸$SUD$0Ph@j3ۃj,Q\$ \$$l$Dl$HD$P$Gt ]3[ËD$8VttT$@L$DPRD$;u*hhdshhj ^]3[QL$HQP ;t9l$4u9$u ^][WT$RVQV|$0uD$ 3 t$(D$ 9l$8taWL$4QT$3@?3øUl$ W|$}u_3]ËōPd$@u+‹SVt$9>|Fub^uhGhvP* hhvOQS Fu%hhvjAhj ^^[_3]É>tWUPV ^[_]Vt$FtP D$L$F^ËT$ D$V^hhvjo3Ƀ ;uhhvjAhj 3ËT$PHH Vt$tFtF u P V ^S\$ W|$ +uwSUVwr;ustC*+u1v4Fj+u v#Fj+uvFJ+3^]uG+C_[̸$l3ĉD$ D$(PhLvD$j PtL$QVRnFUPVF y_F<^]3[Ã}t_F=^]3[+>;~t}_F>^]3[Ã~ !u F$+ˉN_F^][Vt$ u3^ËFW|$ GVQRW u_^ËF G _^hhvj uhhvjAhj 3@@@ W|$u3_VtWV@uVs^3_Ë^_̡0Puuh0Ph4j̸D$S\$ UVWST$ RD$ L$PL$QT$$R336l$8D$ |pPqD$0uZ|$uD$(SPQ茍 _^][Åtuu tQD$txjh@h$P uSWjl$( D$tMML$t t3T$$RSWPD$(PVD$,QRP!D$0 L$M_][^Y̸<vD$@U3Wt8uu_]<ËD$LSVt$XVT$ RD$ L$PL$QT$$Ry f\$\9\$t tSL$TT$L$DL$D$,D$`L$ T$8\$0D$4ul$<ΉL$D$L;~NjL$H VPRQ ̋D$L$T$ VjjQRD$D$PL$QjujMh jnjj -^̸S\$Ul$WjjjSjUluj\h jpj~j _]3[YVj_h W9 uj`h jAj~j ^_]3[YjjjSD$ PUt$(D$<t8D$ t0^_][Y̋D$HVRD$ PjL$T$ ujth jnhj (^VW|$t7u.Kuhh jAj|j _3^Åt7|$ S\$jWӃuhh jpj|j [_3^hh P D$uhh jAj|j }[_3^ÉFD$PWӃ[_^Vt$Wt>u1u hh jAhj -_3^Åt>GwtP_D$L$ PVQ6c u hh jphj _3^Ã>uh끋_^̋D$HT$VRL$ PL$Qjpzuhh jnhj o^̸̋D$ L$T$hPQRz̋D$L$hPQ\b hfR̋D$hPV̸VWhD$ "RujWhjAhj DD$PFPhu=j^hjAhj lhVnUD$t P_3^YË|$ uWjQ uje뢋R)!L$ Wt QP4 P+|D$PhV ujpWhVTL$T$QjRWPD$P C_^YVZuhhjAhj l3^ËD$L$T$ PD$ QRPVkt^V3^̸̋D$ L$T$hPQRw̋D$L$hPQ,` h6P̋D$hPS̸4̋D$ L$T$h4PQRgw̋D$L$h4PQ_ h4ŐD$h4PQSSUVWh43O-j؃|$XuhhWE CL$;Wt QP PڧD$VPRh|$$~j^Ft~WP=tp|$ ~.t&F tTjjWPF Pt/jEEEtPh4V u3hhjAhj h4VQU _^]3[ËMVT_^][̸6l3ĉ$$$SUVW$WD$ L$33s؃ujghjlShD$ MFT$D$L$AW辔tD$+P2X_^][Y̋D$WPL$PQZ ujPhdhhj 詿3_VW39~+VW9P@RP|tWF;|^_jXhdhhj G^3_h9h0:h  ̋D$L$jPQ ̸膾S\$VWjUhS3EP$ ujXhjAjpj 虾_^[YËL$SD$PVQA~T$ D$RVPL$( V_^[Y̸\l3ĉD$XD$dL$hT$pS\$dUVt$xWD$$L$ $339$T$D$$L$D$~(T$8uP@PW;~G;$|jYL-hQ u4j\hjAjoj 舽jShjnjoj nS{`WT$(RW<{xW$D$0L$8T$$SPD$4QRVPW>0D$~f~^|$\$$++|$L$d$|$BPnPQU@PURl$uʋ$\$t UD$(j@PL$pD$_^][3`\̸Pl3ĉ$L$T$XS$dU$dW$pWD$`SPL$E ~^VVST$RD$(PD$(xPL$(QL$(T$4RT$4D$0PQR D$<ED$8+(ޅ^$X_][3肻P̸6D$ V38W|$t$ thhjnjnj \@PD$ds dD$h hQ uhhjAjnj SUT$RGxVPlL$(l$4QVT$$RUWD$0\$LL$0QPWD$\T$<PL$LQW`VR=<][t!D$L$PVQ;T$( D$ G`PxWxt VD$ _^̸Pl3ĉD$LD$TL$\T$`S3UD$,D$`VWD$@L$DT$<\$\$\$\$0\$ ;u'ȁD$;ujlh,jAjtj ιD$;D$$PL$ QL$_$_ Gp D$D$(Pd$@:u+ƒ ~D$,l$9\$ iD$9\$,4T$HRPL$WFg|;|;|$@t W$|3W RP`tL$O$T$$W \$l$;t U9\$t D$PD$;t PL$$QT$ RT$W$T$TPjhu$P* $Rу2hhjhjjj _^3]$3輮Sj$QjP$R^S,PP L$ PQ3tdj $hdR  tYL$QV$PRVD$$Hh$R9UW;ZhhjAD$ t$hV\$uhhjAF9\$ 6h$QU ;*I4 yFƄ4 F4AtD$$j $hdR  AD$|$L QWtRGD$V$RP(L$G t$h9\$(u.$QU ;@ghhjA$RU$ ;~: y@Ƅ D$|$t$D$|$l$EP@:u +j $hdPӃ UV$QRӃ j4hpPӃ L$4uF>,uj FhLV׃ thhjjjkj 誚_^3]Ê< t t FF< u>uhhjpjkj u_^3]j FhXV׃ thhjijkj E_^3]à SA|Z~-t ˀ0 wFP EFt$[uhhjrjkj _^3]ËH T$UR_^]^]VP4uhAhjjqj 膙3^ËD$WPjjjVL$,T$(D$$QL$$RPQVUV(_^V*Puhhjjlj 3^ËD$WPjjjVOL$,T$(D$$QL$$RPQVUV(_^̸<vl3ĉD$8D$@L$DT$TS\$LUl$TVt$\D$,D$dWL$$D$ 3L$QT$,T$RD$ D$D$D$4D$PL$$QVtR|$%uoWT$RD$PwL$(QT$$RD$$PL$0QV} uA%luUh<j _^]3[L$83趗<ËD$T$4RPl$tBL$ T$(QRD$$PL$@UQt!T$0D$L$$*t;ut$,WT$Ru UL$H_^][3_^̋D$L$ T$VPQjRu^WVV u_3^Ët$t PC^>_^̋D$L$T$PD$QL$RT$PD$QRPh܌h $̋D$L$T$PD$QL$RT$PD$QRPh܌h $̋D$L$ T$PD$QRPhHh@ ̋D$L$ T$PD$QRPhHh@̋D$L$jjjjjPQhHh`=$̋D$L$jjjjjPQhHh`-$̋D$L$ T$PD$QRPhXh8 ̋D$L$ T$PD$QRPhXh8 ̋D$L$jjjjjPQhXh9}$̋D$L$jjjjjPQhXh9m$̋D$L$ T$VPQjR9u^WVVu_3^Ët$t P#>_^̋D$L$T$PD$QL$RT$PD$QRPȟh$̋D$L$T$PD$QL$RT$PD$QRPȟh$̋D$L$ T$PD$QRPhXh9m̋D$L$ T$PD$QRPhXh9m̋D$L$jjjjjPQhXhp:$̋D$L$jjjjjPQhXhp:$̋D$L$ T$VPQjRu^WVGVu_3^Ët$t P胭>_^̋D$L$ T$PD$QRPhdhM̋D$L$ T$PD$QRPhdhM̋D$L$jjjjjPQhdh$̋D$L$jjjjjPQhdh$̋D$L$ T$VPQjRyu^WVgVu_3^Ët$t Pp>_^̋D$L$ T$PD$QRPhth-̋D$L$ T$PD$QRPhth-̋D$L$jjjjjPQhth$̋D$L$jjjjjPQhth$̋D$L$T$PD$QL$RT$PD$QRPhh`.$̋D$L$T$PD$QL$RT$PD$QRPhh`$̋D$L$ T$PD$QRPhXh:̋D$L$ T$PD$QRPhXh:̋D$L$jjjjjPQhXh`;]$̋D$L$jjjjjPQhXh`;M$̋D$L$ T$VPQjR9u^WVVou_3^Ët$t P3n>_^̋D$L$ T$PD$QRPhhQ̋D$L$ T$PD$QRPhhQ̋D$L$jjjjjPQhhQ=$̋D$L$jjjjjPQhhQ-$̋D$L$ T$PD$QRPhXh08 ̋D$L$ T$PD$QRPhXh08 ̋D$L$jjjjjPQhXh8}$̋D$L$jjjjjPQhXh8m$̡8Puh8PSh9jG̋D$L$ T$PD$QRPh hM̋D$L$ T$PD$QRPh hM̋D$L$jjjjjPQh h M$̋D$L$jjjjjPQh h M}$̋D$L$ T$PD$QRPhhM]̋D$L$ T$PD$QRPhhM]̋D$L$jjjjjPQhh@N$̋D$L$jjjjjPQhh@N$̋D$L$ T$PD$QRPh8hQ̋D$L$ T$PD$QRPh8hQ̋D$L$jjjjjPQh8hQ $̋D$L$jjjjjPQh8hQ$̸ ƆD$$L$ T$PD$QRPjL$QT$RD$ D$u Ë$L$VQT$ D$ D$$RPT$ ujShLj jgj 蠆L$Q^ ̸&l3ĉ$$S$U$VW$ jP tDSjht D$P L$Q("hhdjhjxj V3IPT$RVXVtW@Wt̅tEt PuƋ$_^][3t̋D$VjPCuhhdjjyj U3^ËL$T$D$ WQRPVVp_^̋D$L$ T$PD$QRPhh<̋D$L$ T$PD$QRPhh<̋D$L$jjjjjPQhh<M$̋D$L$jjjjjPQhh<=$̋D$L$ T$PD$QRPh܎h7̋D$L$ T$PD$QRPh܎h7̋D$L$jjjjjPQh܎h7$̋D$L$jjjjjPQh܎h7}$̸ Fl3ĉ$$SU$0VD$ $ W$0PډL$Aujzhdjsj~j =3@uL$,uBV9$,tT$RQV D$PVucuL$QjT$ hRD$PjL$ hQՋ%hhdjoj~j 蒂VL3|$$4$,VjjjUWSRnU؍D$8 ;u UQHV$(tT$SR'"D$jjjjjSPhh<$Sƃ$_^][3 ̋D$VjPuhhdjj}j 襁3^ËL$$T$ D$WQL$RT$PD$QL$D$L$( _^][hhjAhj 9rt W=D$t PK_^]3[Ul$V3WUc‹VUhǙ+ L7~FIu;t$~+~VjPq 3_^]̋F SPb؃uaNQb=uNVRpb;>|$tFPYb;'DSS1[ËNQ?b= DSS2[h<hj~hj q3[̸pFSUl$WPa NQaVRD$a‹؋FPa |$tERSA1D$ _][YERSA2NQ{a;V,R[a;tFP?a;XN Q#a;PT$ RCvNPQT$R߈jD$8PL$$QވT$(RTD$GL$FT$E L$D ( L$,^3X,S\$UVWS3`~3l$IVSY@UPtSF-;|_^]3[Ë_^][̋D$tt @D$F3̋D$uËHA̋D$VWtDt>@Pt.L$QVttKu0hKh`jt3hQh`juhj Wt V3_^hNh`js̋L$D$V0FW9WRPxuO V QRq_^̋D$Q T$D$Q T$A̋D$QT$D$QT$!̋D$QT$D$QT$̋D$Q T$̋D$Q T$.̋D$QT$~̋D$QT$Ul$u3]SVWU3~DSU7D$$NPQwuT$F RP2tUC;|_^[3]Ë_^[]̸Ul3ĉD$|$S$U3VW\$4D$$l$u8|$hWiG$3;u4;tMUL$(豀|$$VhW  D7+R$D$4D$,"PuUXC\$4D$( PQRt$D p tPjD$,uPL$@jPQAT$H T$,PI@u+‹؋Fx(puz%yH@uj333;|$|$L$~<0t ȃD@;|L$ L$ L$tD$ D$D$D$(|$|$|$D$ |$ |$|$|$333;~$Iȃ9|t 0B r~v@;|ߋ|$0L$ӋǍDD$0t@PQL$q;$T$$4:D$,S/PFVSL$D=Qz F3Ʌ~B|t19P^v"\Fx|FF|FA;|L$4t$(FRt$,;l$|$hhjAjtj Rt WX3t$$|$(uƋ$_^][3RĀVWiu#jPhjAj~j qRWX_3^Ë7F jWhj{N AV zt[t$ ‹HVPWl/ t;SVVWu/V-[tD$t!T$RPWU uWĕ_3^Ë_^̋D$tt @D$閎3̋D$SV3Wtt@Pt3|$WVw|$8V_^[hhjtDhhjs6=uhhjuhhjr hhjuhj PV_^[ËԨƨ̋ :tT$;t Au3ø̡:̋D$:SVW3f uF4L$PFPQoV 貔teGtYVPtKD$3Pwe\$ AuB@tWPgt _^[WQV _^3[̋D$L$hPQ ̋D$QT$:̋T$HL$>=̋L$D$PR\:̋D$L$T$ PD$ QL$ RPR>̋D$L$T$ PD$ QL$ RPRm@̋D$L$T$ PD$ QL$ RPR>VW|$ t6?t15:t'>t"jPHQP< u >u_3^ËPBP3~tv NQtϋVjRt>uFHL$ 1VPPL$Qj_^̋D$tt D$ 3̋D$tt D$释3S\$VW|$ÍP@u+‹jUGhؕPv ujVhؕjAhj CM_^3[WSVu }$j\hؕjvhj MV`x_^3[PL$Qjt$ fV>x_^[̸LSUl$VWjUVjnhؕW'vjo?hؕPv ؅t,t(L$QUt$WVS1tVw_^][YjqhؕjAhj [L_^]3[YËD$Ul$VWS3~*VSM(D$WPUуuSF;|_^3]Ë_^]Vt$ W|$VWou_^ËL$ QB u_3^QAdA jqhylЃ_^̋D$ SPD$XPML$[t hh jjPn3̸JS^ U3Wl$l$D$ 9n|tl$D$4F@ h<D$ tD$NQT$9nPFTUPNA u&G(tVjFd"n`~hӃy|$u&G(tVjFd(n`~hӃLWL$t#tt-VB tEtuD$ u_]3^ËO D$!_]^Vt$W|$Gt$F@ uZN VjFd$уu_3^ËT$RD$PW t(L$yu_^ËV VjFd҃t_^Vt$W39~|FH PFTQRPN\QVXR;u hh jAhj A_3^Ãu_xFTP{;NTWQv@(tV VjFhFd*҃tFTPG7;|_^ÃuN VW~hFd+у_^ËVB tF Vj~h~dЃV_^̋D$tT$D$P T$D$t=@ @u7HuL$ QL$ QRPw7ÃuL$ QL$ QRP;ËL$ QL$ QRP=̋D$tPuUl$ VWU3&~7WU(P t?VtPVUG;|h h jkjnj 3@_^3]hh jljnj @_^3]S_|(d$SUPVW*Wy܋D$[t VP V_^]̋D$L$T$ PD$ QL$ RPQjЂ̋T$ꀉT$0L$选L$D$@d̋D$L$Ad̋D$@`̋D$@h̋D$@TWtUP^tFVW3~1IVWhRh jjPbWFk ;|^_3_̋D$@l̋D$@p̋D$@|Vt$ W|$uthW6u hh jyhj F>_3^P(xuVuhPt$u pt$t.VNu hh jxhj =_3^ËL$ t Axuxt Axup_^Vhh hf uhh jAhj j=3^hjV= ^̋D$L$H@$pVt$FHWtVЃFt~|u P_FFXtPCFXFTthPMPFTWVj3 G_^̋L$QT$p L$QT$_D$ L$QPR`̋D$L$A ̋D$@\̋D$PauËL$QD$T$jbVt$FtP^D$F^ËL$ N^̋D$ L$T$PQjRVW|$W|u hh jyhj ;_3^Pnxuj>uhPIpt.VLu hh jxhj );_3^ËL$ Axuxt Axup_^Vt$ t=VKuhh jxhj :3^ËD$@xup^Vt$VuVe^̸D&:l3ĉD$@Ul$PVt$PFW~u;wPL$fHfL$$T$ L$& 4_^3]L$@39Dà |HT$PL$ T$$L$( Zt3-t.+t)P@A@A8.u!P@0|9P@0}0A0AZAZu3=+t -jHSX KX@ I K H0[-u؋+URD$L$^FN ^^P^^L^T^d^\^`^h^l^p^t^x^X^|.JF;u!hh jAhj '_^3[;t?W RPMON W8VH;thKMPFPM ;uh롃H^H;t G;tF(F( ;t G;tF$F$;t G;tF F ;t G;tFF;t G ;tF,F,p;t G$;tF0^0;t G(;tF4F4;t G,;tF8F8P;t G0;tF@F@;t 4;t~DFDPQVjF<зj u'VQhEh jAhj M&_^3[_^[Vt$u3^Ë8ujG8t^D$)W|$u3_ËVpD$;t"PoKtQRFp3^_̋D$tt D$6s3̋D$tt D$s3W|$tD@t;V0D$;t&PJtQPgFQ23^_3_W|$tG@t>VpD$;t(P|JtQBPFQr3^_3_̋D$tt D$`3̋D$tt D$r3W|$u3_ËVp D$;t"PItQ RkEp 3^_W|$u3_ËVpD$;t"PItQREp3^_VW|$ HQBP3B~"QVR?pHQF ;|ދ_B$^W|$u3_ËD$ Vw;tPHtGPoDw3^_W|$u3_ËD$ V7;tPHt P!D73^_̋D$uËB D$&̋D$tt D$Fp3̋D$tt D$^3̡:Puh:P3"h8<j'"̋D$uËD$̋D$uVt$}SUW8WF;} l$VWUP/Ft F;|_][^_][^Vt$t%POL$;~|QQG^3^Ul$VEP t$;z|vSW}VWWD$ ؃ E;tGtNQWhT$jMVWE;h};}VWHF;|D$_[^]^3]Vt$u3^SWSY|$;}|$Unu&u3l$RGPS2pD$8;|tOQSp3 WSp3҅‰T$D$Pit0WUSu u%hh<jAjqj Uh]_[3^Ã|$t1Sw;}$NQSv@F;|]_[^Vt$Wt'|$tP W@B3Ʌ_^hUh<jCjsj Z_3^S\$VW|$t$uUl$~+t#PD:PUVWSwM]_^[Å}ǍP@u+‹KVWQ> u]_^[Ãt#uVWM%SBE]_^[ËCh]_^[_^3[̋D$VW|$ jPW] }_^ÅtQ;~VRu3Ht$N;|$tAVPWR >_^̋D$P3uÉD$Vt$Wt>u {ft?D$PW*tL$T$D$QRPW^ut;>t WIf_3^Åt>u>_^̋D$P3uÉD$Vet7D$ PVtL$T$D$QRPVu Ve3^ËL$ T$D$WQRVP3Ve_^VW|$jW=u-hh<jwhj WhXj _3^ËD$L$T$PD$QRVPV _^̋D$VP2uh/h<jmjrj W3^ËL$T$D$WQL$RPVQEV _^̋D$L$T$ VPD$QRPju^ËL$ T$D$WQRVPVd_^̋D$L$T$ VPD$QRPju^ËL$ T$D$WQRVPV;d_^̋D$uÉD$S\$u[Vt$y3UWS;}!l$VSUPp?t F;|_]^[_]^[W|$u_Vt$y3SUW~؃;}'l$VWy@~ut F;|][^_][^_Vt$t!V!L$;~| QV^3^Vt$t!VL$;~| QV^3^SUl$ V3Wuhh`jCjhj _^]3[Ëuu t9V|$ ;}D$P`؃t4WSV_ u9hh`jAjhj t St V_^]3[Ã}uu_^][̋D$uËL$ɁIH̋L$u3ËD$@IRPQ9 ̋D$u39HVW|$ t7u(uhh`jAjmj _3^S\$t=PSQ;L$ ɁD$$IN@NRPQY8ut;7t V[_3^Åt?u7[_^̋D$VP-uhh`jmjlj 3^ËL$T$D$WQRVP u V;_^̋D$QT$>̋T$HL$>̋T$HL$~̋L$BD$̋L$BD$̋D$QT$nQ̋L$T$>R̋D$ T$L$PQP ̋D$Q$T$.̋T$H$L$~̋T$H$L$̋T$H$L$N̋L$B$D$̋L$B$D$̋D$ T$L$PQ$P ̋D$Q$T$P̋L$$T$P̋D$HL$T$BD$`T$BD$T$BD$PL$QT$L$QT$D$ L$T$PQR ̋D$HL$@OL$L$ P{S\$VW3u!hhxjChj _^3[Ë3u wt!D$PGYt6WVu;hhxjAhj Xt WXt V_^3[Ã;u3_^[Vt$Wt#|$tPfW6_^_3^̸S\$V3t$;u^3[UW|$ %D$t>P.l$,L$(PWUQjBuh'hxj VT$/l$(t&WN4t~D$$UPV93 tk|$Ct[Ctu"؅tEu|$uL$$QWSd t&T$VRS D$HSQ~u%hChxjAhj _]^3[_]^[̋D$xu @D$*39H̋D$uËVt$u3^Ã~uFP39FL$ ;}؃~uQNQ^ËF^̋D$P'uÉD$VW|$ t7u+kVu hhxjAhj _3^S\$t,PS^4L$(T$$QD$$RPVut;7t VV[_3^Åt?u7[_^VW|$jWR2u-h hxjwhj !WhXj _3^ËD$L$T$PD$QRVPVJ_^Vt$tl~uFPh39FL$ ;}H~uQNQSvt*V9D$th[hxjzhj n3^ËF^VWTu hhxjAhj ;_3^Ë|$t,PW2L$$T$ QD$ RPV&uVT_3^ËL$ VQV~T _^̋D$L$T$ VPD$QRPjdu^ËL$WVQV5T _^S\$ Ul$VW|$USW u_^]3[ÃVSW utW;~|VW3~u(FPuL$ jQjV_^][Ã~u_^]3[̋D$VPe$uhhxjmhj 3^ËL$T$D$WQL$RPVQu V_^̋D$L$T$ VPD$QRPjtu^ËL$WVQ]VR _^SVt$ 3ۅu^3[Ul$Wu Vu_]^3[Ëttt u0X(+1$=tw PXFQ(D$tKT$RjP2 t7D$Ct&tu"tt=uW!=u WG_]^[VjEhja63Ƀ ;t,D$NFN N@;tVЃu V 83^Ë^Vt$tFt @tVЃV7^̋L$AuË@ tL$̋L$AuË@tL$̋L$AuË@tL$̋L$At@t yuL$3̋L$At @tL$3̋L$At @ tL$3̋L$At @$tL$3̋D$T$V1+u tt^ËB^D$IL$;RA^T$D$VWhhjH43 ;tph8FF~~9-F ;t@F~^~ ~[;t VӃt/nEVPt_^][ËF;t @;tVЃVB43_^][̋L$t#u;Ahhj jP+ËIhhjjQ+̋L$tuAD$dIL$[̸ l3ĉ$$$$t/t$3 ÍT$ D$hT$hL$T$4$$L$HD$UD$PW|otkVWug;}SVWiу+T$u?tu%L$ PQR脰L$ PQRTuWF;|^$ ]3; ̋D$L$ SW|$ P3_[̋D$L$ SW|$ P3u_3[PW_[øUl$ VW|$WUu_^3]YËttVUp_^]YSUO;}~SUQȃ+ujtu#WFRPm OVQR>u=uGNPQu*WFRPOtUC;|[_^3]Y[_^]Y̋L$Q T$@)D$L$Q PR̋L$Q T$`)L$Q T$`)L$Q T$,D$L$A̸FD$ SUV0Wh)hj j 9(l$0~L$4U3t PWh+hj j 't VL$yR;}^FWPHt$ItxuT$RT$(RUPу|u"FPGv;|L$_^]A[Í\$T$Bu _^]3[Ë D$(KHtu+hhj hhjjQ'_^][SW|$u_3[VhThj- uhWhjAj|j ^_3[h]hj j ~&V|$$GVPVt'*V/hehjej|j 3 OQ/hjhj j 9&^_[SW|$u_3[Vhuhj, uhxhjAj}j ,^_3[h~hj j ~%V!|$$GVPVt'VV0.hhjej}j 3 OQ[hhj j e%^_[̸ 6SUVW]hhj j D$ &%l$0EL$4xj\$4hhj j $t$4L$$QVjU{ uT$Rz_^]3[ ËD$tuD$Pu] L$QUhhj j $Uzj\$4P}*hhj j T$D$ P_^]3[ Ã|$ D$~|MQVRxh hjGjP$\$,WS$tD$@F;D$ D$|5hhj j #WJThPMS_^]3[ Ë\$hhj j #_^][ ̸ fSUVWh hj j D$ V#l$0Et$4xj\$4h&hj j (#L$8QVjU4uT$R_^]3[ ËD$tuD$P[ L$QXSh-hj j "Uzj\$4}*h1hj j "D$ P9_^]3[ Ã|$ D$~IMQWRPph:hjF jP"\$,VS$t2D$@G;D$ D$|hChj j "D$ _^][ h=hj j !VZhUS._^]3[ ̸UVW|$ Wit$ D$PUjVEuLD$ tuL$QLZ T$RQh|hjjhj _^]ÅtP_̋D$T$ RT$ A$RP@QIRPQSP̋D$T$RP@QIRPQSP̋D$ L$PD$QHRPQjR]Pj̋D$L$PQMPK ̋D$L$PQMP ̋D$L$PQMP ̋D$L$PQMP ̋D$L$PQTP ̋D$L$PQTP{ ̋D$L$PQTP ̋D$L$PQqTP ̋D$L$PQ`PK ̋D$L$PQ`P ̋D$L$PQq`P ̋D$L$PQQ`P ̋D$L$PQ=P ̋D$L$PQVhhj t/u Vt3^ËD$Fp ^̋D$T$ ;vVt$t PFthP!PʭV^̋D$Vp Fth0 P薭t P/V^̸D$Ul$8SVȋWT$ <;t,ً+B\$D$MQ3衪~PUVR蠪ƒX@u+;uD$WPR  tMQFU;|\$URA;}ukEhhj D$$h F聧hOhQF ~tyWSP EVP诨t9L$ 9tCT$ L$BhhjAjdj _^[3]V_^[3]_^[]P FthP!P褫V _^[3]hhjqjdj i3]̸l3ĉ$$V$W$|$ D$4D$u_3^$3S$\$(u$$T$`L$`$T$,D$  +^$L$`D$`$L$,D$ U+uBh?hjjgj st U+]$D$[_^3-Ë V|$,WRD$D$ ħ~ $|$($ D$OPQ觧P@u+ƒPU+Kuf~t`T$hUhj jT$DiND$DPQk|VPR:_33hahj j)33D$$L$SPEQMj/Rh(PQ~vET$`RP| (|A$ uNUD$QRPuNUD$QRPA tChhj j T$$BL$~~~~ F;thpPe~_^Vt$W3;t-F>~~~~ F;thpP~VQ_^Vt$t P/D$ P2+3Ƀ^̋D$T$ P H €t ɀH ̋L$D$!H ̋L$L$p~L$L$pD$L$H HVt$~uFu^ËD$ NPQ蹡^Ul$W3;u_3]ËE;thpPS\$;u [}_]蠣E;u[_3]VSL~:IWSIPS t9EVP tSG;|ˁM ^[_]V^[_3]̋D$L$ d$:utA:Bu u3̋D$D$ :utA:Bu u3̡W|$uh ؞u7_VWPbt"VP,P6 VQ蹟^WR_̸ D$$$t& $QPtPR跠 h j jD$ h`Px ̡th Pܢ̋L$uËD$Q Pt@uSVWt39qtu9pu yxuytu9Xu yxu9ytu9xu yxu@ u y` xt@ Q P u9qtu9XuIQPu_^[_^[̋L$Vt$W~QVF~_^̸̋D$ L$T$hPQRW̋D$L$hPQp h`̋D$hPAdVt$ D$PQh FT$RPh0D$(^̸Vh+`t$ujhhئjAjfj"3^YSUl$WU35SU3wƍd$:utP:Quu3u D$PWA0ƍI:utP:Quu3u3L$QWY tTUC苝;Vt$_][^Yjrhئjjjfj"WGRhЦPhȦQhj0T$hRb_][3^Y̋D$Vp4~t2W|$QWtFT$RjP ~u_D$^̸Wj|$ujqhjAjej"3_SUVt$$V3膜UV脜D$$p4F|$N׊:utY:Zuu3Ƀt7ϊ:utP:Quu3t F uT$jQR\ t.|$~tMt$$VE;:|$^][_j{hjAjej"D$$P+^][3_hhjojej"OWQhЦRhȦPhjL$@Q4^][3_̸6VFWt!D$PD$ PSl |m7NjShh,WD$tFT$ RD$FSЃj t$T$D$L$VRPjN>Ȼu#hh,jAhj"_3^V_^Vt$V u"hh,hhj"3^ËL$ S\$QV[^V3ƍP@u+ƒ rFj hHV  u1F W= P׃tNFQ׃u_3^3^SUl$ VuWP@u= +ƒrjh\V׃ uX*ƍP@u+ƒrIjhTV׃ u8X= P׃tNFQ׃u_u^][_^]3[øD$VPQD$ u^YÍT$RV L$V/D$ ^Y̋D$Ht@t 8tL$hh,hhj"3ËD$Ht@t @tL$hh,hhj"3ËT$tL$A@t IT$L$̋T$tL$A@ t IT$L$̋D$L$@?H̋D$L$T$ HL$PT$HL$P K̋D$L$@ ?HSUl$Wڅu!j|h,hhj"Y_]3[VUY u%hh,hhj"%^_]3[Ã~(?@uL$GPQ  WU舖Ehh,jihj"T$,WhdRPhXj^_]3[ËF(USVЃ ?@th= U菘l$L$QUFt@PS^[^_][ËF uF0tT{t){t#WSVЋ؃ u^_][ËVS҃^_][hh,hhj"^_]3[hh,jghj"UPhXj$^_]3[̸FSUl$VW3WU3|$؃u*hh,jsjtj"aUhXjT D$(uL$ D$PQuD$,L$ T$RPu+hh,jtjtj"L$4Qhpj Ijuh"h,jAjtj"D$$WPwT$3SVĴD$SWt VD$_^][SV\$P[tL$T$QPD$VRP^[W|$VWLL$\$$T$PQ u.j]h,hhj"ShxWhXj(_^[SV\$ePt%L$T$QPD$VRPP^[ËL$T$ VQL$ RT$ ^[̋D$ L$SPQ ؃u[UVWS3~Ol$WSP@L$RPUQt2D$ t jVP۱ V2SG蛒;|_^][_^]3[̋L$3t$D$X̋L$3tD$8̸FVW|$3D$tt$D$L$T$VPQRt%t!D$PW{L$h@QR_^Y̸ D$PL$QT$$D$ L$RPQT$R$̸ D$PL$QGT$$D$ L$RPQT$R$̸ VD$PL$QL$$3t$T$PD$RPL$ Q̸ D$PL$QL$$3tT$PD$RPL$ Q̸ D$PL$QgT$$D$ L$RPQT$R>$̸̋D$ L$T$hPQRy̋D$L$hPQa hQ̋D$hPqU̸Xl3ĉD$TD$dVW|$hWD$ 3ŏ~3VWǏPL$jPQT$RD$$Pj WF蒏$;|͋L$\D$_^3XU誐ujh8jAjgj"3]S\$VWS3<~?IVS9GuGjPtPUSF ;|_^[]hpUThh8jnjgj"/GOPhЦQhȦRhj8_^[3]W|$ tVtPVjU@hPR ujVhjAhj"^3_ËOPQV ^_3_W|$ujchjkjdj"u3_VjVt&ǍP@u+PWV7 u#VzjqhjAjdj"%^3_Ë^_̋D$T$ +̸<D$$D$@}3t; uh3 - tVP芈t8>u˸^jLjPh4jAjhj"3^̋D$VPuhh4jfjjj"3^hh4j8 uhh4jAjjj"S3^WL$ HP_^̡ h3 P  S\$ |$Ul$Vt$t S|u,h UhaVWS^uhPVLWS3@I|$ th UhaVW~hDOVWWS H@u PV u QVPQh| VDW|$ thX VSG襇;j_^][̋D$%=w\tCt<=uV|$h QthpRVh\RV3ËFjQ@QPR=tËFQ@QPRfZ̸ UVt$W3Vl$D$;uD$$L$(T$UP/_^] ËFHL$OS;tыVPPL$QUoORD$PUу ؅uT$(L$,jRT$([_^] ËGt.SWЃD$tsL$ PD$0h PhQUXG$t1jSWЋ uD$-D$uF3>0uFhhjhjnj"GOPhЦQhȦRhjѹ0_3^ËD$_^ËL$_^Vt$FPju(NVQhЦRhȦPhjh3^ËL$ ^S V>tPӃt F>u^3[À>u^3[ËƍP@u+W|0;t.$QӃtO;u_#^[;tG_#^[S\$Vt$zWhrDvhP uhshjAjoj"s_^3[ËϋӅ~,AA:ABu֋_^A[^3[̸ƴVt$ uhhjkjqj"3^YËƍP@u+hhP@ȃ L$uhhjAjqj"讴3^YÀ>SUWG:GD$V t V t$V t V D$ˀ0 w ˀawuéȀ0 wL$ ЀawVL$ ؈]E?VD$t+(_][^Yhhjpjqj"轳D$$P_][3^YËL$Qhhjqjqj"艳_][3^Y̋T$VWpI@u|$ +ƋVRW  u>t <.t_^3_^̋D$hP!P!|̸覲D$ PL$ QL$T$ RD$ Phh Q t3S\$w8T$w,L$ w D$=wFVN[3[Ul$V3ɃW~_^3]ÅtEd$Ѐ0NG w0"ЀAw7ЀawW ȅu_^UM]̃|$u3S\$ UVWS3vx~wl$WStxpքt':t,t.t JBuB:t>+uF3ɋ@QL$jjPUVQ蝕tSGw;|_^][_^]3[̸D$ SUVW3P\$D$k< < ̓t3us<,uoiL$QPS 3ۍ~E<:uϽ]؅td~'<,u#D؍~tOT$RjSN FFeu>u*h<hjmhFhjljmj" T$(ROD$h= Py _^]3[ÍL$QjPT$ RD$_^][̃ukte?t`>uh stEGPQKxu4WRtPPtuQ+3øW|$Gu3_ËL$ u#Ou GG_;uG_Ã~, NjT$< uVR48^tG_ËT$PGtG_̸FD$SU3UUhPl$識؃;u]3[YSu~EVWUSuQ~ =uv>u~t$tSEt;|_^SRD$ ][Y̸覭SUl$VWjj0UD$̏؃ |4ISU P t$t\Sj0U蘏؃ }ϋl$U33t~-SU5t8uxt$tUCt;|ӋD$_^][Y_^]3[Y̸ l3ĉD$D$$VL$QhJ jj:PD$(D$,D$0u^L$3Ŭ SW|$ u|$_[3^L$3蛬 Ë\$tD$$u~=_[3^L$3o Ãut$;t_[3^L$3N Åt;t|^WT$RV耬+P >jQsL$4D$8;tK+RT+RDPH _[^L$3 ËL$ T$D$L$VFN L$(_[^3̸貫 VW|$ jjjUWޕVW"PPhPR Vt_^S\$VWS\jjjUVHWQWhPR WZth@VOt,_^[Vt$ j:Vh VtL$ ^Ët$ ^ø薪l3ĉD$Vt$Wj:Vh VtL$ {tCt$ t,s_tWD$ PV豛 uVd__3^L$3BËL$_^3/̸$l3ĉD$ S\$,Wj/Sh u_[L$ 3$VS[t+ÍL$ VQ؃tSGT WRV tI;uE^t:WD$PVϚ t^_[L$ 3h$VVf^L$,^_[33C$̡?P襠uh?PhAj̸и̋D$ L$T$hиPQRX̋D$L$hиPQA hи&1̋D$hиP4̸̋D$ L$T$hPQRWX̋D$L$hPQ@ h0̋D$hPA4̸̋D$ L$T$hPQRW̋D$L$hPQ@ h&0̋D$hP3̸̋D$ L$T$hPQRWW̋D$L$hPQ? h/̋D$hPA3̋D$PhR h R  VW|$ t-t$t%PQ3uVGRP_^Ã_^̋L$D$w$pS T$ PËdS dS dS dS dS dS dS dS dS ̋L$D$tw $S @3ÍIS S S S S S S S S hиv.uËL$T$ L$PA̋L$9t3ËD$tQD$ tIQ̋L$VT$ 1;2$$U B^D$IL$vR^T$AD$BR^T$AD$R^T$AD$*JR^T$AD$醫R^T$AD$B^ÐT T T T T T T T  U ̸fl3ĉ$ $$ $S$W T$Rh<h0@ D$Ph<h$$ L$Qh<h @HT$RQh @HT$RQh j@HT$RQh ~ L@hT$RPML$QT$ RhH9Yu/CKSPQRPhh L$$hQ9у:UVWD$3K PhT$jR9D$$ȍ@u|$+OOGuȃt|$OGGuf fE|_^]L$QT$Rh CD$Phh *HQT$hR聏D$PL$ Qhغ]$D$[3WÌU U U U :V U V aV \W W|$ V$Y D$ hܻP98^_ËL$ hĻQ8^_ËT$ hR8^_ËGHT$ QhR7 ^_ËGHT$ QhR7 ^_ËGHT$ QhR7 ^_Ët$ hV7GhjPVg^_ËG8pu-NVFQRT$PQhhR?7^_Ã8uY|$ ShW7$V QhdW6 uhX Wb[^_ËD$ hLP6^_Ët$ hغV6OQV胍^_W 6X WX X X X xX X tY VW>t{FjjUP芉 |_PFPىtsPtdV3f~'d$WVfPSetVGtf;|V7f_^h'hjAj{j"觟_3^h hj~j{j"芟_3^hhjj{j"m_3^̋D$SUVW338u _^][ËHu 9X tQCD$ @ QT$D$jj0P |$L$VQ%}U vPw|$tT$VR@}Uj NtVtKD$W_P31dt L$Vj0Q3k }_^]C[h|hjAhuhjA hahj}jzj"9WpSj_^]3[Ul$Vj;Uh u^3].Ct@PXL$QVR耮KAS ztWhE+FhP(VUW jW>豾KWS$39_^]SUl$Vu^][WSUu8hYhhhj"F u 9Ft~tQFQruh_jPD$PFL$QRPtML$QT$RWF uhhjA_^L$D3Hjwhjrjsj"WS3L$L_^3HVW|$t'PQRD$PVh4WVGtL$QPj D$Gt'@RPL$QVhܼMVǾD$_^̸D$ SUV3WPD$2ۉl$l$l$$l$ Yd$L$0UQYw4Wƍ:utP:Quu3uGGD$:utP:Quu3utD$mUƊ:utP:Quu3Gt0:utP:Quu3uT$0REX;3D$,;p;t|$t|jjRVC{ ;|PV{;t PD$|$uI9l$uChhj{@hhjxjwj"莑GPhXj~ _^]3[Ät9l$tu;V5PV|$$>PD$;t;uhhjzp<;tq9l$t5X؉\$ ;tD2t9WSVt+L$OD$T$ L$_FV^][hhjAjwj"讐T$RD$ PױL$Qͱ _^]3[Ã8u _^][;hhjyjwj"Z_^]3[̸|̋D$ L$T$h|PQR?̋D$L$h|PQ<( h|F̋D$h|P̋D$Vt$Wh PhaV%|$ ?t/j hVlQVt0jhDOVM tj hV7WRV_^̋D$ L$PQAVt$ V腥T$ J4ytI;t yuVR<^ËAP>^̸l̋D$ L$T$hlPQR>̋D$L$hlPQ& hl̋D$hlPq̸̋D$ L$T$hPQR>̋D$L$hPQL& hV̋D$hPUl$ EVP葒L$T$P@Ph QhR#EP3:T ~\SWMVQ6TRj*L$,؋D$0Sh PhQ~#S訸WD$DRP MQFS4;|_[^]S\$CUVWP3S~3l$KVQSUR[tCPFzS;|_^]3[ËG_^][SUl$ 3ۅ^9\$TD$HW|$uP@u+‹@~!hhhj~j"e_]3[Vuu/hjPuL$QVt"hhhj~j"^_]3[hlG؃t@uD$P@u+‹T$CWRP覫 tNSQEQu@u\FVUݪT$RWUWU+uQ|$h= WEL$ hq QvE_][3^jVahd>D$VPA|$t$FWt$B;h= WED$ _][^hhhhj"{KSQhЦRhȦPhj~0hhjnVMhhjAhj"u{hhhhj"R{KSQhЦRhȦPhj1~0̀?@VuGPS@ WujhhHhhj"z3^UVSj# ?@uVSb]^h= VC]^̸FzD$ SU3Pl$ D؃;u]3[YVt$9.t^]3[YWS@t$US@x>u.=$ tQFϊ:utP:Quu3t ~uT$jQPl t ~tSE_@;dD$h= SBD$_^][Y̋D$SUl$ h HQRh PhdW=$tJV$d$FPUvmt"t3hDOWQW >u^thPW][hX W][̋D$D$tuItQA̸̋D$ L$T$hPQRW(̋D$L$hPQ h̋D$hPA̸0̋D$ L$T$h0PQR'̋D$L$h0PQ h0&̋D$h0P̸`̋D$ L$T$h`PQRW'̋D$L$h`PQ h`̋D$h`PA̸|̋D$ L$T$h|PQR&̋D$L$h|PQ h|&̋D$h|PVS37=~IUl$ h UhaW VS=PW!hX WSF<,;|]^øuSWك;h u#VhW: [Vq_[ËCNQh VhpWD$  hjT$(RWhX Wj0_[S\$ Vt$W|$tT{~h VhW {~h VhW {~h VhWi C tVP{~h VhW9 ;u2{,{&{ { u{h VhhW _^[̋D$UP3c;SVt$W|$hX WBL$ UQG;؋ tECtVP({th VhWx [VT$RE:;|_^[]W|$?D$ S_P茽Gu[_VS3:~0VS:W3ɅQjPRSt9SFf:;|ЋOjQ}WR^[G3_ËGP^[_ø_̸sSUVWGj h@PD$3  u\$DG0:utP:Quu3V9t5Ol$QUu'hhHhhj"r_^][YhWVWU0.VU9~tU9HPU 9 xt hhHhhj"8r=|$t$>tKhhHhhj" rthPR W ;thBU:_^][Yh1ttz_^][Y_^h][Y_^]3[Yø6qSUVWh0t$3V\$7SV7D$ PU|Jw`ƍI:utP:Quu3u*OQURJuch0U_^]3[YùTƍ:utP:Quu3u\$kEt\$t$CV\$7;_^][Y̸ oSUVW3|$38D$;ED$(P|$6 \$$L$(WQ6xuQPRSVSJVSqD$WP[5|$L$ PSQK 9D$UR5h03tpD$VP4tPhtKL$H*l$D$(GP|$5;D$_^][ h0Wh0VhmhHjAhj"nUL$QyT$hP R7_^]3[ ̸6nSUVWh|؃u hhHjAhj"WnD$ PD$4L$T$ QR4D$$woPSKƍd$:utP:Quu3uKQW- Ɛ:utP:Quu3uSRWLƐ:utP:Quu3uCPW譳{Ɛ:utP:Quu3u KQWm>ƍd$:utP:Quu3u7S URtbt$D$ FPt$C3;h_^][YhhHjjhj"xlOWQhЦRhȦPhjWo0h|SY_^]3[Y̡u P2 ̋D$}3à } +ȍDËPR2SUl$ VW=3DuG WL2= ;}b}3 }FPW12=@͍I:utP:Quu3tF_^][_^][̸jD$ HwHÉ$uÍ$RP3t ̸jS\$,Ul$(EVWw},l$uL$QPj3u x u-hhpj u hF3}3+ }4+4DWRP0FtNQgVR^D$@PaL$HQFT~FtstoVD$4L$< ӉVT$H.FN Vu;uh3 -uh'VP0/uh_^][hhpjAhj"]i_^]3[Vt$t)Ft"tFP胔NQzVq^̡VWh P2D Nt+t%tVR&F PNQuƉ=_^̸FhD$PVP趃$uYh@jj L$ hDQY̋Ft)8~ HV 8~ @H N f F t^8uYVWR3.~,FWP.8tNQG.;|@u T$R5 PP_SjjjgWQPGD38.~%VGDSP6.W.ODQC.;|^[̸gWG(`SUV3ۍGPSPwPWqW PW P' uO( RkuO(@SSjWWQ;tJ9tO(F;t'xt9tPkG O(_ G VaO(SShWP;tXG(u SjUWO }SjVWO |O(;tPkG$G$V O(SSjSWRP;t29~H O,8~PR щW,_, o(PWSSj~W_0PO(VD$S,L$;}nQVQ,Pˀ =w=T $0 O0) o0$O0 _0O0O0 O0@O0D$V+L$;|hpV?.jjjGWPO3;t9(~ HW4o4 _(PlUUjRWOUUjZWG8OUUjUWG<OGHUD$DPhWN@GL;u|$tO(Wl$ML$;QW9NVqK tOVQP=Yu _(VQPuD$;tCh@jj L$ hDQ}t$D$WQML$;|O(^][_ÁO(O(^][_Ð         ̋F(ȃtF,t8t ËЃ``uÅtèt F4t3Vt$F(u0hhpjj _8hhpjj E F(ȃtF,t<t ^ËЃ``u^Åt^èt F4t^3^̋F(ȃtF,t>t t6ËЃ``uÅtètN4t u3Vt$ F(t F0u3^Ã|$t~^ñtN,ttN4tڸ^Vt$ F(t F0u3^Ã|$t>^ètF4@ttF,tڸ^Vt$ F(tF0t-|$t^ètF4@ttF,t t F, u3^ø^Vt$ N(tF0tB|$tt2u/F4%tF4 u ytF,u3^Vt$ N(tF0tB|$tqt2u/F4%tF4 u ytF, u3^̃|$ tVt$ ȃ#^ËD$H(tH,u3ø̃|$ t Vt$ ^ø̃|$ Vt$ t^ËN(tF,?u;t7t2~0@u,jj~VI |PVTIPF t^3^Vt$ u3^ËS\$ tK8tQPet[^ËFtPS P^t[^W~t,W3%~VW%8tWF%;|_[3^ËptS>PV t_[^Vt$F(u*jrhpjj R+jthpjj ; D$ u^P2u ^Å}L$Q3P VP҃ ^à }% +ȋDDL$QVP҃ ^ËPR$L$P QVP҃ ^̸]Vt$(FwF#t$tL$QP&t u%hhphhj"]3^ËT$$2^VW|$Wt$PVP]t_^ËGhV謦~,CPV軲~MQG;|_^][_^]3[̸̋D$ L$T$hPQR̋D$L$hPQ h̋D$hPq̸̸h̋D$hP!̸Sl3ĉ$$S$VSD$ 3l~SWd$VSiQT$ljPR@GPL$(jPQx@T$,RD$4P$QQSF0;|_$D$^[3>SĨ̸R!$uj|h jAhj"%S3YËD$SUVWP3}IL$ SQ~FjPsVjRststoht,P8hD$P8L$(QC- ;|D$_^][YËT$h R}hh jAhj"UR_^]3[YËD$h PKhh jnhj"#RNVQhЦRhȦPushhhhj"P=j}hjjhj"OWGRhЦPhȦQhjR0t$hV_][3^Y_][^Y̸̸Hh̋D$hPqhH̋D$hHPA̸NSUVWhH3f|$D$,P3L$,UQVj hR uFx t /FjhP  Fx D$NhL$ L$(j؋D$0T$RPQR̳?u t6SPt&L$,Q3E|$;'_^][Ë|$hhdjAhj"M$hhdhhj"M|$thHWthS_^]3[̋D$VpW8hS u;FNVPFQNRVPFQRPQhSP(G_^à uM3F RhS( uh  th S膞G|_^hLS_^̃VtjWϕ}^Ã~tjV賕|F;G~/^ËO v r;ust :u΃vQ:VuvA:Fu3^̋D$PVq>u3^Ë ;~+Ѐz.t/^RV /^̋D$L$Sh UVpWyj@Vj@WӋ؃u_^]C5[Åu7>.uST$L$ ;~+WV u_^][_^]/[;t++;uPWV  u؍uCSV _^]/[̋D$@UkW=h j:P׃~x/uxx/urVpj:V׃uj/V׃uƍP@u++ƅu ^_5]À}.u ;~!Q+UP9uPUV  u^_]^_/]_5]̸JSUl$VWU~D$Ph VhhSWU3~`t$WUL$h QhaS 8uPRm PS衧hX SsUGl ;|_^][Y̋D$IwG$ HWz_ËJL$H`@JPQËRSXRB[ø3ÍI   s   S\$Vt$W|$hPϋNhQϋ_^[̋UVP33~jVQ;u3xuHxuBt"uQuh/u}PF+;|u^E.]^1]ËOQ3~FWVR;u xu˃xuQt/uGPF;|3^]^0]̸GSUVt$WVhU%|$(~w\$D$l$jj0UD$) t:VU%P xD$ui\$uTVj0U\) uƋt$FHP3 ~)NHUQ HuVHRE ;|3_^][_^]5[̸\̋D$ L$T$h\PQR̋D$L$h\PQ h\̋D$h\P̸̋D$ L$T$hPQR7̋D$L$hPQ| h̋D$hP!S\$Vt$Wh Sh,V|$$t PV0 h VhX VUh ShVGQV2hX V-WB(t@tPh ShV_^[̸Dl3ĉ$ $UkWD$ D$|ō$:utP:Quu39tUjUh`hhj"DKSQhЦRhȦPhjG0_3]$ 3qDËKjQeNj[h`jnhj"]DSC RhЦPhȦQ딿0Ŋ:utH:Ouu3u:D$ 8tjdh`hPSXjjh`hsI:utH:Ouu339>u!xujxh`jAD$S- jhXRՃ KD$PQ-uhh`jqL$@hh`TRP3mt9yT$HRUQ CT$HU)nUnhh`jA@hj"BSC RhЦPhȦQhjE44SjhPRՃ Ch PЭD$ u5hh`j hj"-BKSQhЦRhȦPIT$ hL$QR ;uD$ jPőu΋L$ Q褗hh`j C@hh`T)RPktyHUT$RQA (PTSjhHRՃ CPI@u+‰D$Ihh`DPQ7ktkzL$SQHRQAT$ Hhh`jAhj"@CKPhЦQhȦROh@h`jAhh`hhj"i@SC RhЦPhȦQhjHC0|$R"$_]3̸?̸?D$$SUVW3P|$(|$|$|$薎Ul$(|$$fWUd؋C#@t{@uuL$0@PQm3W;}(T$RUWt$L$EuˋD$0WPml$(7|$L$Qt$L$tVGU|$ ;/t$h+h`hhj">hh`h8SC RhЦPhȦQhjAhh`hhj"f>SC RhЦPhȦQhjEA0XVjY|$=t=uth1h`hD$$uXh8h`jAhj"=D$t P:,D$tP9D$D$t$PP2HyT$D$h= UD$,_^][Vt$t-t P;Fth PVVh^̸<D$Vt$VL$QRD$u3^PFP^̋D$QT$D$QT$a̋D$txu3PvAL$̸6<D$Uh@VW3S|$h0 E;S~lWSL$ QjPLtuVRJW=u }u@u#EVPu)MVQt+SG{;|D$ D$H(D$ Vhq St$Uh RE_^]Y̸ ;UVhh3jl$d ;u^3] SFD$UD$P^h.nF Ww@5%u:9t$ tj\$O(t UNt SA[^] ËEu 9EtÅtxtPs?F MQStjT$RjYW$u9t$ v[^] ËL$ QWD$ xjT$RhW_$u 9t$ +PWD$ jD$PhW$$؃u9t$ L$SQW|$@u.hhjj b\-hhjj J\ G@_̋D$BD$L$HL$]h v̸8D$$Vt$$T$RL$VD$L$ u3^PV^S\$CUVWP3}~Bl$KWQv9nuT$HRQ\tSRG;;|_^]3[_^][̋L$A D$W8uUtPW SVR3~-\$G VPSP\tO QF;|^[3_^[_ËT$GRPY\@_Wjvhj Qa u_S\$Ul$Vt$oGtICPR=u ~u[~+~uh Fvt9WVt+t$ t3~u;FFtSPuWb^][3_ÅtE^][_Vt$FPr%uNh`r Q V hpRV5b ^ËD$S\$Wuu_[ÅtPYu_[3Vjdhj` t"vF uVat W$^_3[ËD$t~ NtSV^_C[F^_[̸5SUVt$W|$_@3Vl$u+D$O(D$h PD$_^][YVcD$UP]OQP =RP=PSEuLthQRVw eHNSVRuV;GN PQ GT$RE;0D$|$D$̸f4SUl$Vt$FW3P\$8~TNSQ6URWVtD$jWUPttGD$NQC;||$uvtT$jVUR8t _^][Y_^]3[Y̋GVP3~)OVQPStWRFk;|׸^3^̋D$ u@VRPj t0D$ D$QL$PWVQVyu V<3^ø^̸2CUVW~p Vt$9GtV3_^]YËt$ UVVWSuD$L$PVQStnT$ REL;|_^]YÃuHPQj t0L$L$BQWVSFm]V,_^3]YSUl$ ًCVP3~0IKVQUWt4SRF;|ՋCtjPPSt ^][^]3[SUVC W{tthhhhj.&3^ËF@ ^      ̋PA=4t+w1$ NAËVB ËF@ËNAËVB=t!hhhhj.8&3ËF@ ÍI     Vt$f^t3Vt$WEu_3^ËD$tPHtP7_^̋D$P6u39̋D$VPt[|$ ttPI^Ã>u t 6N ^hThjAhj.%3^̋L$A $jPQP{:L$PQ-_̸f$D$VWPjL$jQ_T$R?P:P苖u!hshhjtj.j$_3^Y謳PztWjjoVwt_^Yhzhjwjtj. $t VSs_3^Y̸#D$VWPjL$jQ^T$R?D$(hPFytWL$QjjxVvT$$R4P讚;tRD$PPG;t;V:yhPx uhhhjsj.N#_3^YËL$T$QRT_^YVt$PC>t/t"hhhhj."3^ËNqv u3^Ã>u tWxPtWR@uTPW蝮_3^Ë_^Ul$EVP=t0t#hhhhj.I"^3]ËMqu u^3]ËSWR3\$~5IWP8uHSQt0RG;|Ut1_X[^]hhhhj.!_[^3]̋D$VW|$WP~hhjjWD_^Vt$Ps<t2t"hhhhj.!3^ËNqvu3^Ã>u tW5P?tWRmuPWʬ_3^Ë_^̋D$PFuËL$H̋D$PuËL$Vh/hjH VQuC^UVt$ WP3?;t1t$hhhhj._^3]ËNy~ u_^3]ËSR3[~dd$SPW>u=u ttSNQU$t4VhMhjjRBPC;|[_^]hPMUN[_^3]UVt$ WP3O:t4t$hhhhj._^3]ËNy~u_^3]ËSR3h~aSPg>u=u tSNQU4t4Vhnhj jRAPC;|[_^]hUU^[_^3]WP蔦tRVj3Wt6>u t 6N ^_hThjAhj.^_̋D$PfuËu~D$:tx tPQRxy_yD$tS\$ Vt$ Wt Vujrhjjoj.L_^3[ËPk8wS$T _^[V=&V2VGVBtWPq_^[Åu*W&l_^3[hhhjoj._^3[   3   ̸FUl$ WU*u_]YËV@ t{D$hPquhhjijnj.?^_3]YSL$QjjVuohVljjhVYoT$8SRPu tH ` ߋT$ ^jLh0jAhj.y3^̋D$L$PQP;' ̋D$L$PQP;) ̋D$L$ T$PD$QRPhh ̋D$L$ T$PD$QRPhh d̋D$L$jjjjjPQhh0 ]u$̋D$L$jjjjjPQhh0 M}$L$PD$ PQ L$ T$PD$PD$ QRP! L$ T$PD$hPD$QRP SUVt$WP/VP/ uNY3iT$ L$PD$ SUWRPVQ _^][;L$PD$ PQ ̸l3ĉ$UV3t$usPi-$t!nPijjhUdfujPhHjAjkj.hD$PWb ~2VL$QUc ;uphT$RWb Wb= ujjjqWet4|0$tPSUuBjlhHhjkj.Pt$;t Ua$ ^]3 þVtWVgV:a;u_^Vg^Vt$VP,thhHhjmj.3^WjVu_^ËD$S\$PWLg[_^Ul$UuP,thhHhjvj.?3]Vt$u+Ut90ujhHjjcj. ^3]WVU|u_^]ËD$S\$PptjWUn& \$[_^]Vt$V赇P+thhHhjyj.3^Ul$u+V t9(ujhHjjcj.L]3^ËD$L$PQjVB:~WUVu_]^ËT$$S\$$R݋ϋ[_]^̸VW3VVD$PVQr$D$$RPQT$,R$u h$hHhhj.vD$ hPP=tL$ WQ{T$ R+L$ VQS.jjV'+ <|$ u? UC=;|hhHhjqj.~ _^]3[_^][hhHjpjqj.U _^]3[̋D$SUVWP U3~TSUV! u.L$T$QRV<D$ VP~-jjV< 3UCt;|hhHhhj._^]3[_^][Vt$VP#thhHhjpj._3^Ul$u+Vt9(ujhHjjcj.,]3^D$ tFH A VB @D$S\$ u|$u&u"uC[]^ËL$QPV u[]^WUV<u_[]^ËT$(R4݋ϋ_[]^S\$UVW|$SW3uhhHjAjj.M_^]3[ËD$ L$PVQjjj VwZVW$u&h hHjgjj._^][Ëν_^][hHhHhhj.3hNhHhjhj.3VJt)D$ u"PD$ jPVu V3^Ë^̋D$u胄VPLu^S\$@u jVu#D$ SjPVuVI[3^[^W|$ uhhHj~jzj.3_VtD$L$PQWV/u^3_S\$ @u jVPu$T$SjRVuV[^3_[^_SUVWwWD$\$$t$SjPD$ PWAuhhHjcvl$U3~#VUPW;tBUF];|@u jW)PuL$ SjQWt"_^][hhHjAhj.jt W_^]3[̸S\$UVt$$@D$ l$D$ WVjPjjtGhPW t/VjSUWu,hhHjchj.W_^]3[YËL$Qf6؃t܋CRPa_D$(tŋL$QU1t(T$(VjRWtWD$D$(PrR|$s_^][YhhHhhj.^]3[Y̋D$ SUVWPuhZhHjAjwj._^]3[Ë|$W3N\$$~'IVWISPUtKWF#;|@u jUPuPL$SjQUu;U_^]3[hKhHhjwj.'Un_^]3[_^][̡EPUuhEPhGj̃~uj%PFujThjAhj.3j-NQFHARj  FËPtjGhjlhj.;3Vt$V^̋F WP3~TN WQu >}*"u >}u >}V RGP;|FP3>~5$NWQ68u >}VRG ;|ҋFQt >}VR3~FFWPH9u8}>}VRG;|>_}S\$ÃVWtdthhhD$@8u$hhhhj._^3[P%t$FtY_^[P資t$Ft5|$W諣NPQL tWVPBP$ uhhjAm̋L$u%D$ tQD$t IQÃuD$tI3Vt$Wu6|$WPFQ莣 uIWAVPBP$ _^Ãu(|$jjW蛟G8 tNPQ_^Ã_^Vt$PCtjGhjlhj.3^ËFu^Ë@^SUVt$WP3tjGhjlhj.3Fu3XS34~@VS6t u Rt/OQUtSF;|_^][U_^]3[Vt$W|$t6hhjGjPK F t P+W肤F Ft PP~_^̋D$@u%L$ tPL$t @PÃuL$t@3̋L$QT$ Vt$W3P|$ t!jGhjlhj.5_^ Ëvt$;u _^ ËNS^ Q|$UVWR~FD$$P3sL$$UQmVWRtD$$PE?;|Qt6hhjOjQF t P蛉WF Ft PND$~~D$(S3US8uxVWRatSE;|Qt6hhjGjPF t PWFF Ft PMD$~|$t$NGQ|$#;]D$ [_^ ̋D$L$tQ D$ tQD$tQD$tI̸ SUVt$0F3ۉ\$ Q.P(Pk ;T$R'jj4V}MWSSBtGjWPj4VZ~WX_uhhjAjgN QjUT$RD$$PL$Vjj jjQ) hPF T$RPdL$ PQL$Q( T$0RD$jP} ~uL$ Q,$T$4hhR8"D$ t]L$0QPT$R= ~5D$Vjj jjPsBhhjnhj.tD$ t P#L$Q(^]3[ ÍT$R(D$4L$VPQR^][ ̸Vt$$W~ D$u&h hhhj. _^ËFSQP Pi؃ u [_^ÍT$RD%F PjSL$jjj3x PVu hYhjrhj.NQT$UR D$PL$0QT$R/% #hjhhhj.MD$;t hphjxhj.%L$,r;u2st':uvW:Qu vG:Athw-AFN @QRPL$ Qy؃ hhhhj.3ۍT$R$L$p_^][3K`̸L$ $PQD$`.3YË$VPD$RjhPL$Qb^YVW|$3~OWVts-utdV2_3^ËD$VNVPF PW-t$>u ktWQt_^WG-_3^Vz P4etD$L$PVQ- øVWhD Pd|$tjhW h) Pdtjh)W h-Pdtjh-W hPmdtjhWi t~jWtjjW,tVhW%t?j@Wt0jWtj(W%t_^_3^SUl$ VWP tjGhjlhj.3vu3^S3$~CWS&;t%Vw|NERQt0SG;|hhhjlj."_^]3[jjj3PVuhhjrjlj._^]3[jPjj3U_^][̸ fS\$W|$SWuu#h7hhjfj._3[ UVt$ t$PxjjW萑hBhj CjPihChjOjQR4D$0] }tE>} 3EUPWR t$,uCD$PSzL$QPauh`hhUVRrD$HQ3 ~OT$BWPPjL$(jQ/*T$0Re V=f ;tD$HQG踵;|\$(T$BP蠵;ue(t%VWt$NWQyuBW(hhjAjfj.tPUz^]_3[ Ët$C t7@Xt0UjjSЃuhhj}맅hhjo땋\$0} uE cuET$RD$|$t WUh3Wt$t.L$ U@uUuD$$L$ PQ~u_FFUP ^]_[ ̸`l3ĉD$\UWD$ P39n u1huhhhj._3]L$\3`ËNQT$WR V|tCH9T$RD$(PL$Qo T$RD$(Pjj3V@jWjj2V(VGN hhQ4sP uhhjAhj.XV RD$ PL$WQAou&hhhhj.W)T$FRWPu L$ QL$h_]3`S\$UVWPtjGhjlhj.c3Cu3hU3~'WUL$ t%UG迱;|ًKQ_^]B[_^]3[W*u_VP6suW^3_jXwjFNT$FRP^_̋D$@HL$̸`l3ĉD$\UVt$lW|$tD$P3vNQT$WR"D$ PL$,QT$R 9l$xv D$ ;tj~hjyjuj.Nt$(r;u2stW:uvLQ:Vu v?A:Ft7hhhjuj.mL$ F QT$,RPE tL$QL$l_^]3 `Vt$PCtjOh jkhj.3^ËF^̃~uZP/qFuj]h jAj~j.3j@NQ Pj) FËQtjOh jkhj.[3Vt$PstjOh jkhj.&3^ËFu^Ë@^VJt+tL$P jjQRu%V,hh jAj|j.3^Ë^̸VSUVt$WPt jOh jkhj.y_^]3[YËFD$7PoPou|$jjWEgW衎؃uhh jqhh jOjQ D$ ^~t 3VPWR tkC t7@Xt0UjjSЃuhh j}3hh jo!D$HUQu3hh jAjej.>tPU;r_^]3[Y_^][Y̋D$8thh j|hj.3ËL$@tPL$ tPL$t@̋D$8th h j|hj.3Ë@PT$̋D$8t!hh j|hj.OËPBD$̋D$8th#h j|hj.3Ë@L$H̸Ul$W3|$9}t#h:h j|hj._3]ËEL$QSZ VD$@WP5u^[_]V޼Ujj hjVA hJh jnhj.BKSQRD$(PjV~uL$ hQh Qz uhVh jAhj.;SCRPL$(QWV蠼~ T$ D$H RWQf 3D$V#t WD$^[_]̸&D$ QSUj VpF3ۉ\$;u'h{h hhj.>^]3[WSPʵu_^][WüD$Pjj hjWҰ hh jnhj.F PQRD$PjWԼL$hh Q ؃ uhh jAhj.tiv FRPL$QSWyhh jhhj.:/ED$tURP4EPc ]L$MW耯t$u t S; _^][̸vD$8t$hh j{hj.ËL$T$@$D$D$ L$@QT$RøSUVt$WPvt jOh jkhj.)_^]3[YËvt$D$l$$ t hh jvjdj._^]3[YD${Pit[PiwtD\$4t"PhNAVztD$HWQhGh jAjdj.<tPW9l_^]3[YD$QD$D-t,t u) l$$;"hh h hjdj._^]3[YËT$ D$,L$(VVPnQP2NT$ESP$uPhhhjAhj.eL$Qht PSUUW3Ë$_^][3Ġ̸SUSuD-D$ ;s]3[3ҋuVhhhW4L$,D-+PQ΍T$ +RQSU+RD$4PVST$T+QRD$HPVSHjjjjSWVL$(QVSN2NV2VF"N2("рu&Q;rT$QPD$ P I \$WVVP ^][̸D$SUl$VPtȍD3;s^]3[YÁwtgU҈WEЈGMSWUROC ;v+˃QTR藨\$VWD$PWSBVWL$(QWS4(T$2^][Y̸l3ĉ$$$@SUVq3ۍL$\$h Q\$9^u8hWhhhhj.^]3[$3ĠW~R=}G8u,ȋQBD$OQPD$ Pj D$uhlhhhMQhPbP8 u#huhhhhj. $WjjjPT$4RyD$ jPRL$ QRD$,Pv} hhhjfhj.dFPWL$$QNRVQRP̅} hhhjhj.] }L$ Qr3ҍD9 ;hhhPD$u؃ MD$ PQMT$R F T$XN F hhhQ؃ uhhhjAhj.Qv V>RD$PSL$,^ u hhhhhj.LL$]MD$T$ R;t$u t SfD$P h_hhhhj.3$_^][3Ġ̡`JPuh`JPhKjw̡u  @Vt$VЋL$N^̋D$̋D$u P@ЃuhhDjAjoj!3̋D$t Q D$̋D$t QD$̋D$uh hDjijqj3ËD$A$̋D$uh(hDjijnj3ËD$A̋L$uh3hDjijljS3ËD$uh9hDjkjlj03ÉD$L$]S\$ Vt$ W|$WSV uOuhKhDjjjmj_^3[hOhDjljmjWhhSh`j(3_^[S\$uh[hDjCjpjr3[ËD$L$ Vt$ WPQVE u_^[JPVуt+J PVы PWAGRVЃu_^[̋D$uhhDjijij3ËD$A̸ fu 8 P $QҋL$D$T$QL$D$RQD$ P#D$̸ Vt$u3^ áu PL$QҋD$PL$ Qt$ ^ ̸ 覿Vt$u6D$L$PQV uWhKhDjjjmj3^ áu 9@T$RЋL$ T$QRD$Pt$r^ ̸Vt$D$uL$ T$D$PQRV=u PL$QҋL$$T$ D$PQRD$Pt$$q^u$̸ 膾u XP $QҋD$T$L$D$ BQЃø Fu P $QҋD$L$D$ D$QHT$RӳD$WjP,uhhDjjrj%3_ËD$Vu(h(hDjijnjW35 ^_ËT$RWPAЃ W ^_̋D$WjP+uhshDjjjj蕽3_ËD$Vu(hhDjijijpW3 ^_ËQWP҃W ^_̋D$Vh" P(ujghDjjdj3^ËL$T$WQVR=V5 _^̋D$VjP*ujxhDjjgj踼3^ËL$T$WQVRV _^ø 6D$VjPI*uhhDjjhj[3^ áu PL$WQҋD$T$ L$ D$BVQVT _^ ̸ 覻L$t'D$tI$$PQD$ n 3 ̸ fL$t.D$t&I$$PQD$ .t@ 3 ̋D$Vt$WxVWu_^ËL$ QVRt"VW FPwNQnVh_^̸ 覺W|$u3_ S\$Vt$ t[KD$ PQ|$t$Zu_pƊ:utP:Quu3uW u$CT$ RPD$|$t @^[_ ^[3_ W [_ Vt$FWP葆Q臆3_^̋;t):utP:Quu3uFGt-Nt&:utP:Qu u3;Ft3ɅL Vt$ W|$ q_^Vt$u3^Ã~uh@ h? Ftݸ^Ul$}uaS]WSx+VWSFP=NQ4V.y^t S;URU _[]SUVW臀؅hhj tsl$ōP@u+hxhW tEWUP{D$ F^HVQՅthth!h _^][Sz~t VM_^]3[̋D$xtPD$ P Vt$t=~t7F@ FPh B PNh@B Q蚁V^T$ڀ^̸O̸OVhhj t D$HVуu Vn3^Ë^̋D$uO@K@̋D$uO@M@̋D$uP̸6SV3W\$|$ ;u _^3[ËƍP@u+U@PW|$0OQ@tWFQu;;t4 t FFQu"L$QL$0FIFQCt;uFtNFЊiu.;u F;uFL$A FoFCDMt;DF> tjFFFQ=FVEe؋GHuȋVFQtN;tHtN;uhxhj F t$t|$uT$T$D$,P@u+h@hPVF .L$,iAu+AQL$0QPT$$VRWt$L$Ɗ:utP:Quu3t-VW_u#VWuhhjgD$ L$QPW \$0D$D$RP[hhjZL$Qnt U!_^][L$@3蚫Dhjhjeh{ hhhjAjyj腫T$RD$t PD$4tL$$T$$Rh$ND$Hj PAL$PQhj/G9D$8ttP9Gt$t)Ft PJFt P:V1L$P_^][33譪D̋D$Vh" P0uI"%=uhhjrjxj聪3^hhjjxje3^ËL$T$WQVRV_^̃=uruVh+hjv tEL$ D$QM T$FD$VQVF Fho u V 3^Ë^SUl$ VWj.U t+ōP@u+‹ءP3p~5 WQpVSUR tPGo;|_^]3[_^][SUVWhchjٿ3r D$PIL$QF<Fn9ntvtrCtT$RVЋ~Dupuh~VP(nu^hhjAjsjl[ t tVӃt)Ft PFt PV~_^][C_^][̋D$ L$T$PQRjËD$@̋D$@h@ t PHP@uVW+h1x hW u_^WLHPVWh V Wh4V$_^W|$uhLhjsjwj23_U- SV|$ttIPՃtGGuL$QWh ؃;tR?tMtsǍPI@u+t8|$tRՃtFNPՃuL$$+QFVW T$$RjjT$, ~t{T^[]_̸D$ SUl$VWhH\ PQD$& ujjWj*uFnFhpV؃u D$ph`VPSUVu9VD$hhPjuj貥WhXUhPj蟨(3_^][Y̡P%l~RV QkB tVЃHFPNQVRk^Pk̸趤l3ĉD$S\$ Ul$ V;uSuWVvu>u%hhjqjvj赤VhPj訧 ][L$3uUWVg LuGhhjmjvjdUhD$$j P:L$,QhWhxVhPj5@L$][3WzPjx_S\$ V WQj~>ut1WRit PFPVy^[ Q*j_uRijDYVt$t8D$ tPjV& u'D$ thjV u ^UPVu]^SWU3i~;t$SUiL$$xQVpD$tUCOi;|ȸ_[]^SUVW3S32l$tZu tOjVW "D$t0ƨ%ru!'D$L$PQW ؅u VaW_^][f̃= ug 踢D$j0Pj* CV=j @PlthV7VbVj ^ ̸SUV33D$l$D$v؉\$$;.hSWjWhlj c D$;t$47oo hG;j^<hlW"L$ A;j`hlWT$ B ;3;~L$Q,I ,@;|S|$$Ƃ3ItD$PSD$ >CL$SD$0+QRP_KD$(9 8u9#tp@u+|9 ut$$j~T9 >hlQ3 Ɖs3o|$ t' u|$ tbH3ۀ\È@F\$ u݋\$(L$4;uW>uR@RT$BPdhX @P  ;@F;l$4}ED$(VUQL$(Qh @P  D$t$_StD$tcuh @P  t9Ft PeFt PF t PV^]3[Ë^][̋D$Vt$;| F3^ËNu F^ËT$RPlF^̸趝S\$Vt$;| F^3[YËD$ L$PQjD$u F^[YËVUWR[dl$$3D$~:FWPPd؅t SՃtS\$S"ku=G;|$|ʋ\$V<t PfNT$F _,]^[YËNPQFeSF~f _]^3[Y̸趜VW3|$t$BD$;t$$FSUPwc.;ljD$ |$t$,L$VQR^c33ҋ؅~!tp@u+B;|L$D}PQ!tzT$B3~, tt u\@A@u F@;|ԋL$T$(@ I+VQR ;uD$t$@;D$ D$8D$D$L$QvD$ ][_^_^S\$ Vt$ W39>~:F<t,N <t S҃tF SQ!ju!G;>|ƋVSR au_F^[É~_FF^3[39>~6F<t(N <t S҃tF SQhG;>|_^[W|$Vt47x!IG<t Q,dyWR G t PGP7aD$ SUID$PGP"a؋,3u~;t PF;7|$~ I;r;v t P{F;7|t$OVQ`P_ t$y][WRh`W?^_̸|̋D$VWwSt$|$$` PNQ~RPFu_3^Ë΋QNjRQ)~_^ÍI]` ` p` ` ̸h̋D$ L$T$hhPQRI̋D$L$hhPQL1 hhV!̋D$hhP$̋D$L$hhPQ0 ̋D$Phh̸̋D$ L$T$hPQRGH̋D$L$hPQ0 h ̋D$hP1$̃|$uD$QR*&̸̋D$ L$T$hPQRG̋D$L$hPQ/ h̋D$hP#̸̋D$ L$T$hPQR'G̋D$L$hPQl/ hv̋D$hP#̸X̋D$ L$T$hXPQRF̋D$L$hXPQ. hX̋D$hXP"̃|$uD$QR̸̋D$ L$T$hPQRF̋D$L$hPQL. hV̋D$hP!̸4̋D$ L$T$h4PQRE̋D$L$h4PQ- h4̋D$h4Pq!̸̋D$ L$T$hPQRE̋D$L$hPQL- hV̋D$hP ̸ ̋D$ L$T$h PQRD̋D$L$h PQ, h ̋D$h Pq ̸<̋D$ L$T$h<PQRD̋D$L$h<PQL, h<V̋D$h<P̸̸̋D$L$ T$PD$hhQRP[Vt$FP袮L$t]tjmhjnjhj!O3^Ãu!FtHyt3F ^øF ^jghjhjhj!3^ÃuGW|$~ t6VBHQuVBHQGVB@_^jXVt$FPҭtEthhjpjmj!耒3^ËNAt PyVD$ B^ËNAt PUVD$ B^Vt$ VŧNb$xi t$FF\jPΕ(NQF3^Ët$jF讲Ft$FFjRrFjQejVJ^Ët$FFjR jΦNQ^Ët$FFtmjPߔt\j葦NQ^Ët$FFt0jP袔t^hhjpjnj!蟐3^Dh h h ]h 1i h D$PL$T$AQUVt$ FPqt"thhjqjgj!^3]ËFL$QphSWP-V3V~$WVVQ ;tyVGoV;|t;JGt/SKWWV9U u5Wl_[^3]W\hhjAjgj!g_[^3]ËD$PUT_[^]Vt$FPbt!th6hjqjdj!3^Ëv>u'Vuh>hjAjdj!ގ3^W|$hAhjOjQWRRTuW_3^_^Vt$FP販t!thYhjqjej!`3^Ëv >u')VuhahjAjej!.3^W|$hehjO jQKWRSuW_3^_^Vt$WjP谑|$W+2NPQa VBPڮWd:P.NAV z|$hhj GjP蝰L$,jjQ~YPVPRG tF@Xt?VjjWЃ~_^Ãt#hhhhj!_3^hhhhj!ˌ_3^S\$VW|$uOD$PS~wL$QŢPu$hhhhj!k_^3[t/T$WSRVjtD$VPuV_^3[_^[Vt$FP2ufFNQBFHyuhhjAj~j!ˋ3^ËЋBT$ HRPFNQ^hhjqj~j!^Vt$FP蒦uNA^ËVRyuF@^3^̋D$L$tQD$ tQD$tI̋D$t L$QVt$FPt)thhjqjfj!谊3^ËNAVBL$ QP0P^W|$jPQu_S\$S.OPQ t*WBP耫S 7PԯOAW zu[3_VS1tfF t_@XtXWjjVЃuh.Fh4hh;Vh:hjCjP^_[_h%hhhj!茉t V^[3_Vt$FP蒤uL$ APNRQPR2 ^3^Vt$FPRt)th^hjqjlj!3^ËNqVrW|$W@7u hehhjlj!_3^É~ _^Vt$ FP£w]$r FMNQBuHjWNQB+FHAu&j5VJA VB@u3^ÃH L$^Ëq q q q Vt-D$ PVtL$VQ'u V3^ø^Vt-D$ PVtL$VQu V3^Ë^̡OP~uhOP#h8Qj̋FPWuFËNQBvFt 8u@3V:Ptujoh j j}j!Ɇ3^ËD$QPP u jvh jm4PjjoVu 7^VP$ujh j j}j![V3^̸SUl$EV3Pt$-؃;u^]3[YWVSXu_^][YWS^UjjhjWS#hh hhj!贅L$ T$QRD$ PjWe^~sL$hh Q uhh jAhj!Y9T$ D$RPL$ QVW^~T$E RVPإ 3D$SEWRt VRD$_^][Y̸薄D$SUVW3WPكpWu_^ ][YVi^SjjhjV|R#hh hhj!zC PQRD$PjV{^L$hh Q謭 uhh jAhj!oC @RPL$QWV ^hh jhj!3߃3\$tT$ QPR D$L$;V!Qu t W_^][Y̸t&l3ĉD$pD$|SUVW$O3Q|$$D$t$t$ t$33t$,t$(t$0]w$z GhpzGPh@X HT$(L$$;ugh$h jtjij!ւ_^]3[L$p3袂tËGP@X HT$(L$$;uh/붋GPpT$Z3D$,UI~1$VUIP|$o teUFH;|ڋ|$ D$tP|$Dt:|$  PD$uQhNh j jij!t$t VD$t P_3^]3[L$p3螁tÍL$QjhPSSD$8hQS/P*t$D ~T$0URbtD$jjjjSPVT$L$@QRz Px D$4MQPP l$4PjjoUD$4ul$$ UPBVD$8C D;yl$D39\$0PPD$ ;u[hh j jpj!:}hh j jpj!}3ahh jmjpj!|3Bl$PWtw3C~JSWCUB NPR!uFHUBQPtzWC:C;|hh jsjpj!~|33 C~e\$HVW CSL$(QT$$RWP'}WFB;|&D$HPL$ QT$R! |L$ D$P3WhQ|$ 6T$@D$ WWWWRPc(L$8QD$RP,L$Q(h@h PD$8D$;ЋD$RP豵zt$;uL$T$(L$T$|$D$P>(\$ ;t:L$SQu(SVVdT$$D$4 T$D$|${L$WWVWWQu;tSVV |$t$;tT$(RVV |$D$$;u D$ D$$L$ QP5l$D|$ 3ۋUR蟕t$PuSSjUu;tFL$<;~PAPD$,PSShPD$@a9\$,tD$,t$$PV_^][03ۋt$;tL$QVV! t$;tT$(RVV D$$;t PtD$4;t PcD$ ;t PRD$,;t PA_^]3[0̋D$VhPtH$WjjxVtIPfP0;tRVhP uhh jljj!x3^hh jDjj!x3^Ë^̸ fxVt$(FD$WQ͓PǎP 7T$R*FPjWL$QT$$RZD$ VjjjjP&F h`V PL$ QRaL$ PQD$P趧 L$QAT$0RD$jPpZ~nL$,hh Q5 D$t`T$,RPD$P:Z ~8L$ VjjjjQpEDhh hhj!nwD$t P譢T$R萧_3^ ÍD$P{L$0T$ FQRPؗ_^ Vt$FP2t3^ËFtptjV=Vz=L$ ;~QVx=@^ËD$UPUtqtmVWS3>=~.$VS9=UQΚtSF=;|_^3]ÃuWR<tGjP<_^]3]S\$j3d[uË@S\$C Wth>P?|$W;=C u_[VW3u<~-VWwP>|$W<Cu_[VW3;~-VW;PPCVP<tWF;;|^_[^_3[̋Ul$VWu<uB_^3]P3;~-IVP;Q ;tHRF];;|֋D$L$PQU膹 tVR4:uRV'_^3]WD$L$PQUHcWVR!; uW_^3]_^]̸psl3ĉD$l$U$Vt$|W$L$ QD$ D$虡WRt.GPthh jrjqj!sMSRΎ؋ƅthIhPtQD$PjjxVD$$tsP`Pf;tnL$Q`P;tWVuhh jljqj!s[T$ RHL$|D$_^]3rphh jD‹T$RD$(P"t} AWZ90L$QT$@RD$,PD$$S uWRu h:KL$9 pT$<r!$;st,:vB:Fv J:NjS0PPT$,R PD$PW "hUh j jqj!qD$$L$PQT$,RG yD$PҜL$ }QuD$IhIh je둋GVRPL$0Q\Vdhlh ji_D$̋D$L$SY P.[̋D$L$SYP[̋D$L$ T$S\$PQR [̋D$L$ T$S\$PQRd [̸Hpl3ĉD$DS^ j4[u:PV1u,hh jAhj!p3L$D3oHÍ$PL$QW诟 uhh j뼋$RD$PV uhVL$H3oH̸x6ol3ĉD$t$SU$VL$(W3QD$ \$,UR|G]w$ ED$uaMQPGL$ Q؍|$ VL$T$RD$HPQ訞 7T$MRQ D$HPR跎 EPujjjU'L$A T$hRihsh jkEHPBL$ D$;u,j2D$;uhh jAqMQB\$ 3St$46VS4~NR L$ Q؍|$ iT$RD$0PF P;4|$,'@EHAD$;;jND$;uhh jAUJA EPpT$ D$EHQR?9] D$P0MQZEpMQD$BP9] L$QUBXgNQxhQh PD$4VRD$(PL$4WQt5T$$FRWP t$\$ FSt$2;"ShYh jTD$PjjVJhVݻjjhV.L$,D$,P; D$L$,Qj"T$RG&;+l$(Ug=T$RjjU芲PD$,PD$u}hnh jAhFh j juj!^Vh%hLhVh jujuj!^D$,PlPhdjaL$8Q#%(l$L$QSA$tENPuh{h jAjuj!Z^jjhV蓱t$ h$RUG ~0tP$PV h$QU Ѕt>T$ RVAbu#hh hjuj!]ViV$uND$P38$~;L$VQ5$T$VR($PWSU? ~JD$PF#;|D$$D$(9D$u t U:UL$Q#D$,4hh jijuj! ]h5h j{juj!\3$_^][3\ĨWujLh jAjtj!\3_SUVjWptIjWt:D$\$$t>SjPD$ PWu(jXh hjtj!S\WZ^][3_u6l$U3"~#VU"PWtUF";|@tjjjWtPuL$ SQW t^][_VujIh jAjvj![3^L$ PFPQT$VjhR^̸[D$VhPFt->u(NQT$詔PFQT$ Rj ^Y3^YVʔujfh jAjwj!Z3^ËSWP1IL$Qgp\$ ~WFujnujrSWt^ujvh jAjwj!{Z_[3^ËVzFL$VQ_[^Vt$j2V3t3^ËD$ u joPjj2VK^̋D$u,PPq!uhh jAhj!Y3PD$jj4PVt=D$L$ PQVy tT$Vjj3Rt^VZ3^ L$ T$PD$PD$ QRP1QۿL$ T$PD$hPD$QRP,RSVW|$GP t؃uOq3臿T$L$PD$VjSRPWQU _^[[L$PD$ PQX ;L$PD$ PQE WujGh jAjuj#RX3_ËD$PmT$OQD$RP̌ujLVujPh jAjuj#X^3_ËL$Q~m^_Vuj^h jAjpj#W3^hQmD$ F^Vzujqh jAjqj#W3^Whm|$WmPN tL$$T$ QL$ RT$ QL$ RT$ QRPW?* F_uj뎋^V uhh jAjrj#V3^jljFwNuhQPD$PS uhh jdjrj#V3^Ë^Vt$FPqthh jyhj#RV3^VNPQ茋^V*uhh jAjsj#V3^jVuhh jxjsj#U3^W|$ WlPtL$T$QL$$RQP谒T$D$L$ RPQW uhh jAjsj#{U_3^ËVBHQDVBxNQBPvL$,T$D$jQRPCPW|NQBFHyuhh jgjsj#T_3^_^Vt$FPpt3^ËNQBL$T$ jPQRPFHQR;^̋T$BD$p'D$HQT$ PR Vt$FHQothh jyhj#/T3^CVPBPf^̸$ ̋D$ L$T$h$ PQR̋D$L$h$ PQ h$ ̋D$h$ P̸| ̋D$ L$T$h| PQRG̋D$L$h| PQ h| ̋D$h| P1̸ ̸8 ̋D$ L$T$h8 PQR̋D$L$h8 PQ h8 ̋D$h8 P̸ ̸P̋D$ L$T$hPPQR'̋D$L$hPPQl hPv̋D$hPP̸̸̋D$ L$T$PQjhRRC̋T$D$jL$ QjjSRD$ C̋D$ L$T$PQhhRB̋D$ L$T$PQhhRB̋D$ L$T$PQhhRBS\$u3[UVWS3h~*l$VSfPk ;tSF>;|_^]3[ËOQ'tWjR%_^][̋D$HhQnu3Ã8u@@RP@̸hOl3ĉD$dD$lL$pT$|D$D$xL$$$L$8wxm@PST$PL$Qj`؃ u'jWhjejxj#O3[L$d3dOhËCUuh P=TT$ L$VpW8RD$8PQ[$PD$$UjWVRP`$u0jahjkjxj#OS_^]3[L$d3NhËL$D$QT$(RP$T$$PUjWVQR$u jghjjS貄$PD$L$,QL$,T$@RjPQT$Pj@R聠D$HjPu,_^][L$d3ANhjQhjejxj#KNL$x33NhSW|$ ?uu_[û3ۋD$VuaL$T$QL$$RjjjQPtVRsuWuMt23D$PQutR3_ø_̋D$VP\tD$PVhu V;3^Ë^øLVt$WVD$ D$tdD$PV転tL$QPW( t6T$ RVƢtL$ QPW tt$WuWE_3^Ë_^̋D$VWP tkD$tPV|tUD$Vt#L$T$$QjjjRPUV證 tt$ WPuW_3^Ë_^̸XVKl3ĉD$TD$\L$`S\$hUl$tV3W|$xD$ L$t$t$t$9$u DŽ$9$u DŽ$9$u DŽ$9$u DŽ$;u6;u];jghjhjij#J_^]3[L$T3JX;tvSWtٍT$RD$(PPWkUL$WQD$$tjPV' ED$tPT$(RV &t$U3~/WUPD$PhUG;|Ջt$l$ t'$$UQRD$ VPh V3t$$$$UQRPL$ SQ|LjhS |PS$PVR4jhXS |PSPFP4D$tjPV D$tPL$(QVO t$tjjjT$ VRh Vj3, tt\$SW8u W Wh a S$|jPjjjUWueW_^]3[L$T3GHXËt$D$th a P\t$th VD_^]3[L$T3HXËL$d_^][3GX̸Gl3ĉ$$S$U$V$W$L$QD$S{$NR$D$ PQRWPujShjsjwj#xG3jWL$hQ-$ǃPp ujXhjAjwj#0GWST$RD$$VPFuVYrj`hjjwj#3FUD$L$QPT$ Rh uVrjhhjtjwj#3Ft D$}D$t0L$QƋ$_^][3ZFĘ̸FjD$PD$$@L$$QL$$RT$$PD$ QRP; uhhjujjj#F3ËL$S\$Vt$$WQST$Rjt$ |$,t SVuhhjejjj#EV q_^[̸VEVjD$fuhhjAjlj#xE3^YËD$T$WPL$ QRD$ uhhjfjlj#9E_3^YËT$jVNQL$WPD$,RPQ u(hhjgjlj#DT$R=p_3^YÃ|$$tD$WPҖL$Qp_^YVujEh jAjmj#D3^ËWjP`H|$WZN A_t jTh jw"jEeVBFxu"jNh jAjmj#1DVx3^Ë^̸<CSVD$,W3P\$0q|$pWɵW ;|$(} _^3[6 L$QPKV N AVAuhhtjAjzj#5_3^_^̸HF5l3ĉD$DD$dS\$TVt$TW|$du诳L$lPD$lPWQVu,hhtjnj{j#A5_^3[L$D35HËL$`T$ RD$PQSVTu,hhtjmj{j#4_^3[L$D34HËT$ NRD$PBPT u,hhtjoj{j#4_^3[L$D3z4HËL$P_^[3̸c4H̋D$Ul$WuōP@u+jG|hW] u_]Vw3Ʌ~*T;|L$D8D8^t9L$t_]Ul$Vt$ƙ+Wt|.tGj\hWE2] u_^]3Ʌ~S);Έ|[D8_^]̋D$L$PQqP{G ̋D$L$PQQP{H ̋D$L$PQ1PE ̋D$L$PQPkE hhPD$Phh1PD$PfVt$PM=t3^ËNRM=u{PFHQg^Vt$PM=t3^ËNRM=u蛌PFHQg^̸1GHQ$@VQT$Rjg u^YËP#ML$VR6L$L$Vg ^Y̸ f1PL=t  ËL$SVjQRj tKWD$ PC8L$ QT$R7 _t)L$T$D$VQL$RjjPjQO u3^ ËSRss^ SUl$VW3~,D$UPVW#tWFu;|^][^]3[̸lV0l3ĉD$hD$pSUV3Vt$0D$,L$l$(l$$l$l$؃;u^]3[L$h350l,D$;tWSl$T$RSGPHK u W@L$,jQWT$(RWD$4PBxL$ML$0T$ D$jQRPiPWFu#jXhjgj}j#9,Vn_3^_^Vj hjU 3t6FFF FFFD$@tVЃu V'W3^Vt$t@ tVЃVV^Vt$@u^ËL$T$W|$WQL$RQVЃ~~F_^Vt$@u^ËL$T$W|$WQL$RQVЃ~~ F_^̡TPe"uhTP*hTj*̸TVt$t%F9D$rD$ L$VQ@P* F^Ã^Vt$N9t$s^ËD$8u@VPD$P* ^̸U̡ UP!uh UP*h`Vj*VjDhjpS ujGhjAjzj&)3^jpjV*F`PVj FXrm^̋D$3ɉHHH HHH H$H(H4H8HtCNt1׊:utY:Zuu3Ƀt@Ã>t~u^[̋D$SUl$W u@Pt8t xt_][_]3[à t tu#uj{hljChj&_][V u1pPt(| 0^_][hhlh]PPC31tyt ;s@;K$ @ Qt^_]3[Ë^_][DP@u^_]+[DȍQAu+RDtP$@u^_]+[áWP@u^_]+[Dt$ȍqAu+Ph AQW^_][ËWp@uR+h @PW^_][^_D ][hhljnhhlhhj&l^_][Ð {     o Vt$uhhljChj&3^Whhljj <39FXhhljj tFTuWL$QL$V^hhljxhj&m^Åuhhljxhj&I3^ËD$PD$PD$PRVу^̋D$L$jjPjQ}!hhlhhj&3ètVt$t{D$ ts~@t8jPjj Vl~$L$T$QL$RQPVO3҃^Ã|$t e^hhlhhj&S3^hhljChj&43^W|$D$ @VFjPjj W,VWuhBhlh-jjVjWs}hJhljnt7|$thThlhjjjVW/3Ʌ^_S\$uhdhlh{tjSjVW3҅[^_èuhvhljnIj D$PS L$ ;t!9ujjPVW3Ʌ[^_h}hlhhj&[^3_Ã|$t ^_h<hlhhj&^3_h)hljChj&g3_á4̋D$4̸SVhhj3j \$8t$09u)h@h q;D$$P Ul$4W;|$4It$(T$RPML$X;uLhhj? ;F aFV;T$,^PL$0VQRED$8NPQtL^ 9\$~~~ ~~~F F F$bF(;u'hh jAhj&cV_^3]hh jj WPU;u WVQU^ 33hh jj ;t VG_^]̸=WV}zh jjjju#hh hhj&3^Yhh jj :=W}5Whh jj WPWD$uSW\$ 0[tD$^Ỹ~$tF jjPQ7tÃ~$UttV(R荵|aS3W~BF(SP聵N PQR4t"jjWP6WuC;|_[3]_[]3]̸U$W39;uR69{ u!C;u _3]ĜPP4C Vu4hh hhj& Q/^;_3]ĜËS RP~1C;u Q{/hh jhI9{uaSRPJ1C;thЃ=s: Q{{Q/hh hhj&;d^_3]Ĝù|$8D$ D$+T$ D$RD$ PL$ QYD D$0K D$4 D$8 D$< UD$D&CKT$RPUуuF3Rss.h h jmhj&3t$8^_3]ĜÃ{~?Uu2{~'hh jghj&Y^_3]Ĝ5^_]ĜSVW|$D3;uhBh jp9thJh jdD$8$ |$;tǍP@:u+ƒs3F ;t P;tW:F 39^ _^[_^ 3;^[39\$_F^[Ë|$;tǍPd$@:u+ƒs3F;t P;tW9F39^_^[_^3;^[ËD$w _F^[hlh hWu_^[ËD$w _F$^[hwh hk|$;tFǍP@:u+ƒr3W8;uhh jA5N(jPQ _^[hh h hh jwhj&A_^3[3    2 X # VWPVTto WQVt[h:VtIh:Vt7h Vt%jVthP V t^V3^VZtVVh^?^Vt$ W|$ |;t5}t;D$tVD$PW _^_3^̡WPV$t> WQVPt*hVthWV,t3@tV>tVu Y^oVI^ $$̋D$ L$T$h$$PQR̋D$L$h$$PQ, h$$6p̋D$h$$Ps̸$̋D$ L$T$h$PQRg̋D$L$h$PQ h$őD$h$PQs̸$̋D$ L$T$h$PQR̋D$L$h$PQ, h$6őD$h$Pr̸@%̋D$ L$T$h@%PQRg̋D$L$h@%PQ~ h@%n̋D$h@%PQr̸%̋D$ L$T$h%PQR̋D$L$h%PQ,~ h%6n̋D$h%Pq̸%̋D$ L$T$h%PQRg̋D$L$h%PQ} h%m̋D$h%PQq̸ &̋D$ L$T$h &PQR̋D$L$h &PQ,} h &6m̋D$h &Pp̸P&̋D$ L$T$hP&PQRg̋D$L$hP&PQ| hP&l̋D$hP&PQp̸&̋D$ L$T$h&PQR̋D$L$h&PQ,| h&6l̋D$h&Po̸&̋D$ L$T$h&PQRg̋D$L$h&PQ{ h&k̋D$h&PQo̸l'̋D$ L$T$hl'PQR̋D$L$hl'PQ,{ hl'6k̋D$hl'Pn̸'̋D$ L$T$h'PQRg̋D$L$h'PQz h'j̋D$h'PQn̸X(̋D$ L$T$hX(PQR̋D$L$hX(PQ,z hX(6j̋D$hX(Pm̸(̋D$ L$T$h(PQRg̋D$L$h(PQy h(i̋D$h(PQm̸(̋D$ L$T$h(PQR̋D$L$h(PQ,y h(6i̋D$h(Pl̋D$Q T$̋T$H L$n̋T$H L$̋T$H L$>̋L$B D$̋L$B D$̋D$Q T$.̋L$ T$̋D$ T$L$PQ Pg ̋D$HL$T$BD$PT$BD$T$BD$@L$QT$L$QT$D$HL$`L$L$@D$ L$T$PQR ̋D$QT$>̋T$HL$̋T$HL$̋T$HL$^̋L$BD$̋L$BD$̋D$QT$N̋L$T$̋D$ T$L$PQP ̋D$HL$T$BD$pT$BD$T$BD$`L$QT$L$QT$D$HL$L$L$`D$ L$T$PQR ̸SV3ۅjVj hJh)PD$$)D$tojjVD$D$jP9VtL$ WQ T$ R觽L$ jjD$PhnQtD$t P^[̋D$ W|$ QL$(_̋D$W|$ QL$_S\$H UVWjhnQl$$UjBhnP}}_^][Å}_^][_^][Ë Q VREHWQPFRP_^]@[Vt$ H jhnQ) }^ËPB PL$jPR^SV3W|$tOthjWP tX|$tFtDQPt4|$t舓Ft WP*tVjho V_^[VW37tTt$ t/t)PtPt PWŸuWjhp]hpW_^VW3גt,D$ PVvtVWhr V踒_^øVSV3t$؅D$P#Ul$W9ut@CI}tm|tvhtcW1FtW苐tLMjQW t9VFxKVQ艞tuSjhs  D$_]SD$ ^[YË^[YVt$Ft P'Ft PV^Vt$W|$jWnPFh,)Pn_3^ËNWQh t ~VjjjRx+F_^̋D$uVt$PFP)3^W|$t.NjhgQ( uVWRb)_3^ËFjhlP( 3Ƀ_^Vhh)jA3P-FD$F D$$F~FFNhh)Q Fu3^ËD$ u VPhl)R&m ~ًD$tPVptË^̸S W?t$PӃuG8uuhh)jsjvj'_3[YQӃtGGuhˀ?uh뿀?VtRӃuF8u>uhh)jsjvj',^_3[YUj D$PWF L$ 9td$RӃt FFuF>tAƍP@u+D0D$PӃtL$D$HD$RӃutShh)jrjvj'v>uWh)ja ]^_3[YVh)Wh)jC]^_3[Y]^_[YU- Vt$WIu7FNV PQR% FNWPQ% ;=nHd$' FT$RjjP'DL$Wj QՃ /VFNRPQ& ;F>Nug늉L$t< t< AL$uND$PjjQN'L$AL$0҃tmhAL$F~!f)F AnL$u- F=w-DFN9VVjRA#F_^3];~1_^3]ʃNFT$RjjPd&;FNQT$RjL$ t_^]-tt[t_^3]ËVL$QjjR&NT$$+QЋF RP}#~X)F}NjjjQ%V jjj R%~)DF jP)"_^]ËV jRF jP "_^]Ðc% c% & & ̸D$L$ S\$ VWjPQSD$ET$ VRujS!u܋Ft P Ft PV_#D$^[Y̸Pl3ĉD$LD$XL$`S\$XUl$dVWD$L$K>t P肿S)Hu3jth)jxjej'V_^]3[L$L3PPyNjGL$T$RD$ PSQu6hh)jfjej'V,_^]3[L$L3HPËT$NRD$ PQ t\MjST$RUD$(PQRt;D$VPL$ QRF t!|$t7F PnWhF uV_^]3[L$L3PËL$\_^][3PVt$ W|$ QPu$NWQRuFOPQ_^Vt$ W|$ QPu8NWQRu$FOPQuV G RP_^̋D$L$ T$SUD$ VWP445h j:Uփ?@X ͍:utY:Zuu3Ƀu\$$ >@ ͊:utY:Zuu3Ƀ\$$8/x/j/P֋uh aL$$VST$$D$$8tKj:Wh t@;)u)PL$ tWT$uhh)jAU_^][hh)jyjrj']t UD$ t PL$t PzT$t Pg_^]3[̋D$PFP`SUl$ VWuK|$\$tW+qWy S&q3SItWPVU _^][Vt0t PD$ D$t QVRu Vn3^Ë^VZ$tD$ PNQu VI$3^W|$ Bt P($p_^Vt$~uFvu3^W|$tB~u ~FtFWP-u_3^hh)jjW_^S\$ VWSo|$PW t:LGt.t$tfVSru1hh)jnjnj'GPG_^3[ËL$GQHVRQjRPtD$$uDSWt\$ S36~#VS8PWtSF;|_^[̋D$L$̋D$Vpuhh)jljoj'/3^ËQP=mthh)jhjoj'3^VPR;^̋D$uËH L$f̋D$uËB D$Y̋D$uVt$}3FSWx W;})\$VWQStWF;|_[^_[^W|$u_ËGSu3L$@tVt$t@t Pb^D$tOD$tW [_̋D$Vt$jPV }3^Åu3Q PR?L$ T$QL$RT$QRPBL$$t^̸SUVD$WP \$ SXl$,uh@h)j{fL$T$RSL$z~hHh)j~jsj'3D$(|6L$T$R+SL$<}hRh)jjsj'3|$ tyWuh^h)jz(D$L$Q+WD$}hfh)j}jsj'G3SW}hnh)j|jsj'3_^][ËD$QT$鞍̋L$BD$鎍̋D$uËL$tL$tPL$ tPL$t@ ̋L$39AVWt]D$ PQt@|$tFFt,hmVFPPW uV9_3^_^SUVt$W39x u躍A 9z L$(GPQ}D$,tW RP`P-L$QsD$_ttzCsl$$u(hh)jmjgj'#WJ_^]3[+stHVUt:\$ txFt%SPhtt$B WPauW_^]3[Ë_^][Vt$~ upF u^ËF W|$WPu_^hh)jjW_^̸ l3ĉD$D$,L$0S\$,Ul$uNQ[VRRFPI V@^Vt$t#FhG PzN QVj V^U3uhh2jCjmj(蔱]Ãt tu uhh2jijmj(e]hh2j tT$ 39L$pP8X H]̋D$ UVt$WPQYtJ|$u xGt+T$D$ L$$VFNWVRkv_^H]V_^]Ul$Vuhh2jCjlj(莰^]W|$ uhh2jCjlj(h_^]À}St2h PWӃthh2jhjlj(-F>uԋL$0T$(\$4|$,t$QRY[tF|$u wGt'D$L$ FnNWVRnu_^H]V_^]̋D$L$T$ S\$jPD$QL$RPQ3d[̋L$3t(Quhh2jAjgj(D3ËL$T$S\$jQL$RT$QPR[̋D$L$T$S\$PD$QL$RT$PQR3[̋L$3t)Q uhh2jAjjj(褮ËL$T$S\$QL$RT$QRPD$PJQ[̋D$L$T$PD$QL$jjRT$PD$QRP$ËD$SUVW3333ۅtPvuh>XD$tPXuhH:D$ tP:uhRD$$tVP؃uGh\h2jAjnj(螭t Vt Wt U_^][ËD$,L$(T$PQjjSUWVR$_^][S\$ UW3;uhh2jCjmj(_][Vhh2j p ;tP^\$~~~ 9{u tC;t ~~~CVP]r;^_]H[Vz^_][ËL$3t)Quh{h2jAjfj(tSjjjjPD$3PSK1[S\$ UW3;uhh2jCjmj(_][Vhh2j p ;tP^\$~~~ 9{u sC;t ~~~CVP]q;^_]H[Vz^_][ËL$3t)Quhh2jAjej(tSjjjjPD$3PSK1[̸l3ĉD$D$IS\$(Ul$(WtSUPу _][L$3۪22 2fD$2T$2L$:T$fD$fL$ u_]3[L$3胪ËōP@u+VptÍPd$@u+thh2VVT$$RWVUW$tVD$ PWVSWVL$QWL$0 ^_][3̋L$T$AQ̸ 薩L$,3$D$D$D$ D$D$D$D$D$$$D$Bt$RQЃu 3 UVt$ @3tVЃu^]FtVh P {NSWQ3o~4d$9ktVWRoPCVЃt{NQGo;|ЋB tVЃt[tR3FP3{o~Hd$>tNSQnoWPV҃tt3FPC?o;| A_[tVЃ^]̋T$uh)h2jCjoj(CËD$t(th<h2jjjoj(ËBËJ|$ t JÁJ̋D$L$T$ PD$ QL$ RPQj ̋T$ T$`L$ L$D$h̡hu hVhmh2j t'3FFF FFFD$P^Vt$PSVG^̋D$t L$H3Ã̋D$t L$H3Ã̋D$t L$H 3Ã̋D$t L$H3Ã̋D$t L$H3Ã̋D$t L$H3Ã̋D$t@3̋D$t@3̋D$t@ 3̋D$t@3̋D$t@3̋D$t@3̋D$uË@̋L$u3ËtuA̋L$t HwA 3̋L$u3ËuA̋L$t HwAÃ̋L$t HwAÃ̸$Ƥl3ĉD$ S\$,UVt$8W|$@ǍP@uc+‹%F u hP?eh NPQӃu)FRPӃu7G8u_^][L$ 3D$ËNV _^]3[L$ 3%$ËNV _^]3[L$ 3$ËNQhd T$(j RM:FPhd L$(j Q8: ;n}RKheh2jejij(ףh2T$(Rh2D$@Ph2j跦,_^][L$ 3肣$ËF;~/Khmh2jdjij(~h2L$(Qh2T$@R륋v uhvh2jijij(L@PWV L$0_^][33 $VjPh2j ujSh2jAjhj(3^ËD$uhu )hF PVj FFFQ ^Vt$ }hh2jgjkj(肢3^W|$ GP i;|hh2jfjkj(Q_3^ËOVQhtIw@ _^VjPh2j ujSh2jAjhj(3^áhu 1hF PVj FFFY ^̸@ZVt$ V%w&xPVxP0  xQD  ^̸ l3ĉD$Sh V5` WD$ jPփ t&L$j QӃt^[L$3ڠ ËL$^[33Ǡ VWhh3jj 5H h h3p֋= |uף|h  h3փxu ׃@x_^V5 W֋ |=4 ;tQ׃֋ȡx@;tP׃h@h3jj _^̡V5 Pj֋ Qj֋Rj֡Pj֋ Qj ֋ďRjփ0^̋D$SUl$ VWt OӃ u F tuj` Pp _^]P[@u+V5 h`Z jh`Z jh`Z jh`Z jh`Z j h`Z jփ0ď^ø膞l3ĉ$S3U$\$tht\$ 9$uD$ P |QT$hR`  ;tt|PX ua |Q8 uMT$ j Rh ;t 9$tW=|_tD$ PUV |D$ uD$9$][uxhX R  =t|D$hP$ D$3fVW|$WSUthxPWlt50 P֋ xQW`P֋xRD  jW2t$PW ][_^Wt  Pxh@3PӋ x-D QՃjWt$PW ~WW:utH:Nuu3t xh03RӡxPՃ ][_3^][_^Ë xQW\sP0 xRD  jW:t$PW _^S\$V3}^[WtaD$Ul$KSjUjPW |1|$$tL$T$ USjQjRW| WW]~3_^[̸l3ĉ$$ =$$~V$VRPD$PQ!L$hQ$ ^3̚{̸<5̋D$ L$T$h<5PQRwJ̋D$L$h<5PQ2 h<5"̋D$h<5Pa&̸5̋D$ L$T$h5PQRI̋D$L$h5PQ<2 h5F"̋D$h5P%̸5̋D$ L$T$h5PQRwI̋D$L$h5PQ1 h5!̋D$h5Pa%̸6̋D$ L$T$h6PQRH̋D$L$h6PQ<1 h6F!̋D$h6P$̸6̋D$ L$T$h6PQRwH̋D$L$h6PQ0 h6 ̋D$h6Pa$̸6̋D$ L$T$h6PQRG̋D$L$h6PQ<0 h6F ̋D$h6P#̸7̋D$ L$T$h7PQRwG̋D$L$h7PQ/ h7̋D$h7Pa#̸T7̋D$ L$T$hT7PQRF̋D$L$hT7PQ>>|>>>|( -( -gggxgggxsS՗sS՗'''%N'''%NAAA2XsAAA2Xs, , QSQS}}}ϔ}}}ϔn7In7IG؎VG؎V0p0p#q#q|||Ǒ|||ǑfffqfffqSݦ{Sݦ{\K.\K.GGGFEGGGFEB!B!ʼnʼn---uZX---uZXƿyc.ƿyc.8?8?#G#GZZuZ/ZZuZ/6l6l333f333fccc?\ccc?\  98I98Iqqqqqqύύd}2d}2II9Irp;II9Irp;Cن_Cن_11KHۨKHۨ[[q[*[[q[*4 4 R)>R)>&&&-L &&&-L 222d222dJ}YJ}Yjj<x3w<x3ws榷3s榷3:t:t¾|a'¾|a'&އ&އ444h444hHH=Hzu2HH=Hzu2$T$Tzzzzzz􍐐z=dz=d__a_>__a_> @= @=hhhghhhghr4hr4ʮ,A,A^u}^u}TTMTTTMTΓv;v;""" D/""" D/dddcdddc**ssssssHZ$HZ$@@@:]z@@@:]z @(H @(H+V蛕+V蛕3{3{KۖMKۖMa_a_===z===zȗf3[f3[6ԃ6ԃ+++EVn+++EVnvvvvvvႂ2d悂2d((lw6lw6õ[wt[wt)C)CjjjwjjjwPP]P PP]P EE ELWEE ELW88000`000`+t+t???~???~UUIUUUIUǢyYۢyYeeeeejeeejҺhiҺhi///e^J///e^J'N睎'N睎_޾`_޾`pl8pl8.F.FMM)MRdMM)MRdr9vr9vuuuuuu0 60 6$ $ @yK@yKcYхcYх8p6~8p6~|c>|c>bbb7Ubbb7Uw:w:)2M)2Mb1Rb1R:b:b3f3f%%%5J%%%5JYYyY YYyY *TЄ*Trrrrrr999r999rLL-LZaLL-LZa^^e^;^^e^;xxxxxx888p888p匌  cƲcƲA W䥥A WCM١CM١aaa/Naaa/NE{BE{B!!!B4!!!B4J%J%xf<xfс>сDU"DU"  NN%NJkNN%NJkQsfQsf ` `<<|>|j5@j5@  ޹go޹goL_&L_&,,,}XQ,,,}XQkָkָk\ӌk\ӌnnnW9nnnW97n7n  VVEVVVEVDD DI^DD DI^ߞߞ!7O!7O***MTg***MTgֻmk ֻmk #F⟇#F⟇SSQSSSQSWܮrWܮr , X'S , X'SN'N'lllG+lllG+111b111btttttt  FFF CLFFF CL &E &E<<PD(PD([Bߺ[BߺXN,XN,:::t:::tiiioiiio $ H-A $ H-Apppppp׶TqoTqogηgη;~;~.ۅ.ۅBBB*WhBBB*WhZ-,Z-,IUIU(((]Pu(((]Pu\\m\1\\m\1?k?k"D†"D#臸O6yoR` {5.KWw7JX) k]>g'A}|fG-Z3`ZPYuh`ZPCbh\j7b̋D$L$g̋D$W|$9Gu_VP@ujThDHjAjwj/ b^3_ËGP@w^_̋D$W|$9u_VPujjhDHjAjvj/a^3_ËPz7^_̋T$BD$RD$W|$9Gu_VPuhhDHjAjyj/6a^3_ËGPOw^_̋D$W|$9G u_VPdguhhDHjAjxj/`^3_ËG P5w ^_̋D$L$%A̋L$39AVt$tFh@Py)F^̋D$HL$DT$BD$ NT$BD$DT$BD$EL$QT$pEL$QT$ED$ L$T$PQRE ̋D$HL$W|$ u3_VWLt$PhHVWF PV1hHVW~(u hHV|PV0h|HVeW/ u hVMPVD/jhX VW~ЬuPh`HVW PV0^_̋D$W|$9u_VPUAujLhHjAhj/^^3_ËPA7^_Vt$FPrVL$RN?D$F^̋L$T$b̋D$W|$9Gu_VPԀu hhHjAhj/]^3_ËGPBLw^_̋D$W|$9Gu_VPt<u hhHjAhj/]^3_ËGP"<w^_̋D$W|$9G u_VPcu hhHjAhj/3]^3_ËG Pw ^_̋D$W|$9Gu_VP蔂u hhHjAhj/\^3_ËGPw^_̋D$@̋D$W|$9Gu_VPt=u hhHjAhj/c\^3_ËGP"=w^_̋D$W|$9u_VPbuhhHjAjuj/\^3_ËPg7^_̋D$VW|$ 39Gt?t,P5buhhHjAjtj/[_3^ËGPw_^̋D$VW|$ 39Gt?t,Pauh"hHjAjsj/G[_3^ËGPw_^̋D$L$%A̋L$39A̋D$W|$9Gu_VPDau hDhHjAhj/Z^3_ËGPw^_̋D$@̋D$W|$9G u_VPDu hZhHjAhj/CZ^3_ËG Prw ^_̋D$@$Vt$tF$h@P #F$^̋D$H$L$P>T$B$D$GT$B$D$P>T$B$D$>L$Q$T$?L$Q$T$ ?D$ L$T$PQ$R9? ̋D$H$L$鐓Ul$VW3|>PUXMt&G~hDOS0FPh S F}‹_^]SUVVVVհ t SW( hWhJWt UW( hWhJWt VW( hWvhJWh^][S\$Wh0KS?|$P\ w ]Qh S h KSVhKSWR3n ~O$~hKSQGjVPRPSHhX S-OQF#;|uhHShJS^tW8] uhSWhX SI_[Vt$ u3^WV|$PhHW hHWVPW'VޮPW)hpKWV&0t>.tFZF^uj>j؃tD$ PSCu7S-hhKjshj/I_3[L$3H ËL$$_[3H V:tjVLu*jfhKjAjnj/HD$hLjP 3^Ë^̸6H$P u7VhhKjzjoj/^Ht$ hLjVmjVu(3^YËL$$D$YVt$hLjV.jV63^VhhKjPNq uhhKjAjj/G3^jPjVG F,0 F4 F< ^̸6GSU3W\$\$ 3(jW D$ PWNDQRWbjF0N,PVуD$QPW?N8T$RV4D$PQV҃ D$L$PQN$3D$ PW9^u 9^u9^ tT'؅FtPS<FtPSF tPStSWtpF(tjWt[VDRtPWt=F(t|t,EQRUEtUWDuEW'hhKj{j{j/3EFHP觼Q_J uhLjV U貝S<&T$RbD$P_][SUl$ VW*tb?u  tRjjSa )tjPSP%6 uJj'V)h{hKjAjqj/DW#*hPhKjAjrj/D_^]3[ËVQ; tU3, ~:IVU) j@ tPR tUF ;|ˋ_^][̸CFSUWP3Q\$33\$uhhKjxz;uhhKjA^jW譱ZWjPGBNDQ!tBRWaF;t/P1 ~"FSP0 PW9NQC ;|VPRPW蕶؃uhhKjvhXPjj2SfuhhKjwF(tF3PtxUSuhhKjtMW~tOjW?؃\$ uhhKjANLQSZ$ughhKj|hj/{BNHQR7Guh MjVs D$ PU'WJD$ _][SWuh뉋VLFHRWP 3~LD$UVt$ 3WnDnHnL$FH;uhhKjAjzj/AzD$UP!FD;uhTMjVjVKUUV t<3t1;t&PFL;tS[t uWhhKjyjzj/)AFH;t8P)QEu#h0MjV ;uVHR#nHFD~HPnH NHQnD#VLRnH " _nL^]̸V@$VPQRD$PVL$j QT$R ;D$PhhTNjdjmj/H@VbNPhdj5C(3L$QT$R^Ĉ̸?SUVW33~!VWPW\Fh;|h%hTNS!i l$u!h'hTNjAjij/?^]3[W3~JVWPD$o ~/CD$ UPWPS WF;|l$^][̋D$PL$PQKc th?hTNjljfj/>3ø̸ v>l3ĉ$$$U$,P賖P譵Px PYPTPj D$u hZhTNj~hj/G>PIhchTNPEg uhehTNjAhj/=qL$QT$ Rnt[hD$$PS ~.PL$$QT$Rhm t-hD$$PS ҋjQT$Rn u2P\wQhE3]$39= Ë$ ]3̸= ̸<D$ SUVWP$WD$tEMQR?a[tSDmtUDumGP轳;uYOQ譔L$r;u=st :u%vP:Quv@:Au _^][Y3t$hhTNjgjdj/0<_^][Y̋D$PuhhTNjijej/;3ËL$PQ;thhTNjhjej/;3øUl$VW33ISJ;}$WSLUPFGt֍G_^]ÅtG_^]_^]Ul$ Vt$ SWjjUV3$SV0>uyvMP+<;9ucspto}tJPxu:jQv8u(W @RPuOVQR]:tt$VC+;`_[^]_[^]^]̸:l3ĉ$ $UVPIEP>hL$!jQD$D$(B:WNw ]T$ D$ NEWPv~}D$ }tzSD$]$KUQR-tE|$u ,fD$D$Њ@u|$+OOGuȃ]|[|$u L$T$D$ h hTNjkjhj/9t$ ƅuT$L$QhNPhNRhpNj;Vd _^3]$ 38Ë$^]3̸w8Ul$V3}D$ uHUQR{uF^]SD$PjjUW~"؃tKIUz3Ƀu#ST$RVjUWF"؃u[^]Åt S轐[^]̸7D$ SUVhPu3!HQT$@QT$Rj D$ t{]jWAPS*ubS~8W ;~&IVW PS|*WF;|UD$D$^][h#hTNjejgj/ 7UcD$^][̸ 6l3ĉ$$,$0SU$03V$0D$$L$ \$ \$\$\$;uhhTNjfjjj/6zVRQthhTNjrjjj/X6LWV٪;W SWSSjVD$8蕢thhTNjjSUVe D$;PL$SQyT$0U|$  l$ |$UjV |$hT$0RW萅 SUVW0hhTNjm:D$$thhTNjjSjXD$hhTNjnjjj/5_D$PʊL$hPMQT$RQ$8D$$^][34 ̸f4SUl$ Vt$,W3V\$,>WE|$ \$\$\$\$t"MUD$(PD$0QRPxQEt.Vt hhTNjqhj/14EtM VQ EtUMVRUEtM]D$PV|$t$L$0T$QL$RT$t$0|$ 3E tE VPjtwE@t2;t.W|$,uhhTNjohj/P3?Et1M$|$(QuhhTNjphj/3D$T$(RBD$PlL$Q>^D$( _^][SUVt$WVVʊV3P tD$SWP Eu_^][VW|$W3tD$ VWPV_^VjBhNj([ t#3FFF FFFFF F$^jFhNjAhj/1^Vt$uhNjLhNFT 3FFF FFFFF F$^Vt$toFP>'NhPMQV RFPNkNQ\VR,F PN$Q芉$3FFF FFFFF F$^Vt$tVqV[\^S\$Ul$VuhNjvhN^S t3U1WSnшt%PtSF _u^][Ã&SLW蔧Pj Ft_W.WvhhNPFYFt4FPWONPQ`0St:P6F u-tUk_^]3[V[VE[_^]3[Ã&_^][̸/VWD$P3!T$(L$ QR5D$P_?tG|$ jh Wu ~$ƍP@u+PVWX ~3VZL$Q _^̸.l3ĉ$$V$jPD$ hPJPL$QVjhX V$(^3̸.ĄSUVt$hNVD$P4 3ۅWd$L$SQWPVW\u Ph\VjjWVmuh hNVaWRVjhX VC ;{_^][̋D$Q4IuT$aPhNR PDT$PhNR VW|$WĤPHua PhDt$ PhNVhOVW4PjQRVe(_^S\$VWh S3輘tWWWV芤uSh O @P   VB|_^[̸,S\$ UVWh S33Ot$t[tPWWWVnrW3D~OSWFtPU$WC;|Ћt$Sh@O @P   h[WSV}{ _^][YS\$VWh S3蜗tD$PWWVƮuShdO @P   V{_^[̋D$uCD$VhOhOPi u$hOhOhO @P  ^̋D$VW|$hܼWP3Xi u#hܼWhO @P  _^ËL$T$PQR _^SW|$ 3۹Pǐ:utP:Quu3u_[VWtXONJ:utP:Quu3uPPjjdVShVt(hhOjhj/_*WhOjR- t VU^_[̋D$ SV33WuH|$D$h PWPg u-h PWhO @P  V"}_^[PtL$VQ_tV|_^[̋D$ VW33uD$L$ h,[PQng t!PtT$VRthPMVV_^̋D$ SV33WuH|$D$hPWPf u-hPWhO @P  V_^[ËL$QPtT$ VRtVض_^[̋D$ SV33W|$uDD$h$PWP]f u-h$PWhO @P  V_^[jPAIu h$PWhOL$VQ`tV^_^[̸'D$SVt$Wh4PV3P\$3e ;t/Pzv;u h4PVhO @P  fUW*~Ol$ SW(Ht@jPoHtBVUtVWC;|D$]h= W0D$_^[YËL$h4PQhO @P  ĸ&D$S\$VWhDPS3P|$3d ;u#hDPShO @P  PWu;u hDPShOVtUV ~Gl$ WV Ht@PBtjD$TPL$@QBjT$`RD$LPBL$P@QCjT$0jR*^_][L$,30ËL$8_][330Ã|$SUWtWl$tO\$tGtV.C}P%FK}Q FT$jVR0 }C D$|$PuD$tYR1V1FFE NMD$0t,FP NQR1FP1V1L$ Q>      t h d ` T H @ 4 (                  x t l h \ T L D <  .\crypto\cryptlib.cERRORdynamic%I64iOPENSSL_ia32capService-0x_OPENSSL_isserviceOpenSSL: FATALOPENSSL%s(%d): OpenSSL internal error, assertion failed: %s pointer != NULL.\crypto\mem.c.\crypto\mem_dbg.c" thread=%lu, file=%s, line=%d, info="number=%d, address=%08lX thread=%lu, %5lu file=%s, line=%d, [%02d:%02d:%02d] %ld bytes leaked in %d chunks not availableOPENSSLDIR: "/usr/local/ssl"platform: %sVC-WIN32compiler: %scl -D_USE_32BIT_TIME_T /MD /Ox /O2 /Ob2 -DOPENSSL_THREADS -DDSO_WIN32 -D_USE_32BIT_TIME_T -W3 -Gs0 -GF -Gy -nologo -DOPENSSL_SYSNAME_WIN32 -DWIN32_LEAN_AND_MEAN -DL_ENDIAN -D_CRT_SECURE_NO_DEPRECATE -DOPENSSL_BN_ASM_PART_WORDS -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DRMD160_ASM -DAES_ASM -DVPAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DOPENSSL_USE_APPLINK -I. -DOPENSSL_NO_RC5 -DOPENSSL_NO_MD2 -DOPENSSL_NO_KRB5 -DOPENSSL_NO_JPAKE -DOPENSSL_NO_STATIC_ENGINE built on: %sFri May 11 04:08:14 2012OpenSSL 1.0.1c 10 May 2012.\crypto\ex_data.cno dynlock create callbackfips mode not supportedINT_NEW_EX_DATAINT_FREE_EX_DATAINT_DUP_EX_DATAFIPS_mode_setDEF_GET_CLASSDEF_ADD_INDEXCRYPTO_set_ex_dataCRYPTO_get_new_lockidCRYPTO_get_new_dynlockidCRYPTO_get_ex_new_index.\crypto\o_fips.cMD4 part of OpenSSL 1.0.1c 10 May 2012MD5 part of OpenSSL 1.0.1c 10 May 2012SHA part of OpenSSL 1.0.1c 10 May 2012SHA1 part of OpenSSL 1.0.1c 10 May 2012SHA-256 part of OpenSSL 1.0.1c 10 May 2012SHA-512 part of OpenSSL 1.0.1c 10 May 2012len>=0 && len<=(int)sizeof(ctx->key).\crypto\hmac\hmac.cj <= (int)sizeof(ctx->key)OpenSSL HMAC methodHMACWW4   P`.\crypto\hmac\hm_ameth.cW`00.\crypto\hmac\hm_pmeth.chexkeykey.\crypto\cmac\cmac.cOpenSSL CMAC methodCMAC~~ t  0~Pp@p cipherRIPE-MD160 part of OpenSSL 1.0.1c 10 May 2012  ##%%&&))**,,//1122447788;;==>>@@CCEEFFIIJJLLOOQQRRTTWWXX[[]]^^aabbddgghhkkmmnnppssuuvvyyzz||        0 0 0  0 0  0 0  0           0  0 0 0 0  0  0  0          $$  $ $ $$  $ $             $$  $ $ $$  $ $                  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0                            ((  ((  ((  ((  ((  ((  ((  ((          """"   " " " " ((((((((    """" ( ( ( ("("("("(libdes part of OpenSSL 1.0.1c 10 May 2012DES part of OpenSSL 1.0.1c 10 May 2012des(%s,%s,%s,%s)idxcisc2long.\crypto\des\enc_read.c.\crypto\des\enc_writ.c   !"#$% !"#$%&'()*+,-./0123456789:;<=>?@ABCD./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzRC2 part of OpenSSL 1.0.1c 10 May 2012xݵ(yJ؝~7+vSbLdDYOaEm }2@놷{ !"\kNTe`sVu;B=0<&oFiW'C>/fހRr5Mj*qZItK^AnQ$Pp9|:#z6[%U1-]㊒)glឨ,c?X≩ 843H _.G奜w hIDEA part of OpenSSL 1.0.1c 10 May 2012idea(int)j?$.Dsp"8 1).lN!(Ew8fTl 4)P|ɵՄ? Gy 1Ѭߘr/Ḗ~&jE|,G$l iciNWqX~=t XrX͋qJT{YZ90`*#`(yA8۸y:`l>w'K1/x`\`U%U攫UbHW@cj9U*4\̴ATr|*oc]ũ+1t>\3֯\$lS2zw(H;Kkē!(f a!`|H2]]]u#&܈e>#Ŭom9BD . Ji^Bh!la gӫҠQjh/T(3Ql n;zP;*~ev9>YfCoEå}^;uos D@jVbNw?6r=B$7H ۛIrS{y%P;LylO`@ž\^c$johSl>9oR;Qm,0DE ^J3(fK.WtE9_ ӹyU 2`yr,@%g̣饎"2u<kaP/R=2`#H{1S>W\o.ViB~(2gsUO'[iXʻ]=!lJ[-ySeEIҐK3~ˤAb Lw6~д+MەqՓkю%ǯ/[{AI~-%^q h"W6d$ cUYCxSZ٢[} Źv&ϕbhAJsN-GJ{RQ)S?Wƛv`+t恵oWk *!ec.4dV]-SGjnpzKD). u#&İn}ߧI`fqilRdVឱ¥6)L u@Y>:䚘T?eB[k?ҡ08-M]% L&pc^?kh >\D}W7: P tAu8/;21>8TNmO Bo ,y|$ryVw.?rU$qk.P̈́GXzt}K:zfC cdG27;C$CMQe*P:qUN1w_V5kǣ;< $Y,n<pEㆱo ^*>Zw=Ne)։>%fRxL.jxS<- N=+6&9`y#RnfE{7(2åZl!Xeh;/ۭ}*/n[(!pa)uGa0a4c\s9pL ު˼,b`\ndi#PZe2Zh@*<1! T_~}=b7w-_h)5ǡޖXxWcr"ÃF T0.SHُ(1mX4a(s<|J]d]B> EꫪOlOBBǵj;Oe!AyMjGKPb=bF&[$ti GV[ Htb#*BXU >ap?#r3A~_;"lY7|`t˧@n2w΄PU5ai Z .zD4Egɞs͈Uy_g@Cge48>q(= m!>J=+hZ=@&L4)i Av.khq$j 3ԷCaP.9FE$tO!@MpE/f m1'A9UG%ښ ʫ%xP()Sچ, mbhiHפh'?Oz|Ϊ_7әxB*k@5 ٫9N;VmK1f&tn:2C[Ah xN جV@E'H::SU kKмgUXc)3VJ*%1?~^|1)p/'\,(H"m?H܆AyG@n]Q_2Տd5A4x{%`*`lc´2Of#k>3b $;" r(-Exb}doITH}'>AcG t.no:7`L knU{7,gm;e' )̒9 i{f} ϑ^و/$[Qy{;v.97yY̗&-1.Bh;+jLu.x7BjQ满PcKkؽ%=YBD n *Ngd_ڈ鿾dW{x`M``FѰ8Ew63kBqA_^;Z4ٷ,Q+:Ֆ}}>(-}|%rZLZq)GW;()f(.y_xU`uD^mm%adâW<'*:m?!cf&(3uU4V<wQ( gQ̫_QM08bX7 z{>d!Q2Ow~㶨F=)iSHd$m-if! FEdlX [@X̻k~jEY:D 5>ʹrdfGof,ҏ"W##v215VbuZ6ns҈bIPLVq z2E{Sb%ҽ5iq"|˶+v>S@`8G% 8vFšw``u N˅؍芰z~L\HjiԐ\-% ?2aN[wߏWr:Blowfish part of OpenSSL 1.0.1c 10 May 2012blowfish(idx)@0 /kz%?/?!M@`Iɟ'Կ@uИcnafŽ"o;h(Yy#P_w@CV/|-ҢɡHl4ma/T"2*kT:V"AӢ@f/9/Mҹ-?JDvR7,YQoz Zh{.T"5Y/mKdPIf-徐"3;䎴]4K@E?1.eUʱծ-mԢP @"8On ׿r[O/LVSTIiFXEŅc]ՊSW9j7=T*_}x:vbj Bz)^'rgP8ƌDŽZ*'JkѢ*V`C u\B&Ʉq-ls5&5 M{n0f&%HVV^c ϲc|E pPr(pH# yM;-AB G&LjMG\^ |Y#јr8S#/nqFnEV 9q +A|iCHy}B{BIZݿe\ [ ~iC?9zaz UQry吝5rNcZպ60ę _}֡{/6Y DYD̃Aѱ* ;{ B[A%zzӤ0XޘN?wiy{$[Ĭ%5P_aT1bcKU !h]Yfsc=4·~!+g\ab906;Wd/`:5F- 'zy㠌l0^7%oo;j tE'4:NiOM>dY58EfCr3c%N? (Υ'R¦սTUdpfM w&ۄgC!`X0TroSUGڿ]bVhkʃ;n-Ӧ\= wL3{9+^S_aodC x^c"&gI{ڷ"%-U^7rRyL H[k0 cq/޹ S E!5(T<)c)A|-nRPf4,0P1`sY&D\dwR3A+ٺ|o!PaH?ek«dv&4{^% ;MM1$~I,;jx`]sVz\/1Co0TyXR^/2zj0>՚1B°I #ڸ(0q_`ɣaM/Ǚ."płNؼ40y;'ƸaiH?;(ZC/v7ܱӧßn>ƼB7Q(heRwj-K'5.n\ )^XOX{iT̨g&H`K`8# ~8lI `s5GƱVL>#8d^BFzk Od^AE#\;]>rC|m~ll9`qpsv#E@]%=`GK6DήPQH<p}}d^(O= &g.yr?U+HԼ?^!@WNFRWs3NɷdŸW1O g_?@k{C=K۵cUȗn-J(JqoCCl< _P/~׿PZG.Q>pX.0_|r *,]I鎸P'WIoyR}}Yr@EEt]>uOiVA#. '`vteyvvwHNma}/ 4H<0(Ow Vܒ M"7)}V'|@|硴f^aÝ <є`AFv\;x,WGl"}NC~8<=Q8d{h'فI]j~vh]9K9 ;#Im<Eub'z\aBΒ~Brrp }ȡ[(Ob<51)BSjO[}m(Ki\j#MŌ?,-ҖXRg[HJI \EkӉ7`:SRqDIK @sg4|~q6UO/Т`?mPьGnU?墼38Wg} =3{r3O̫]ňv{{uWBdBc+ri/n+_mazgaq%9̸L!gуb>ܷν8\ =Dmn`I:T`H'W+8$ ږ%Eh;}E `P/(b4 ٠m+1+dZ0RXBA\1>26F3S75 {s{OJWdCQz(~c5_ yCdcdJ$_(͸O@C " 0 O7-{$MgQLq_-_d !S^>'_aB%rqK=;&o~~TLmDl߫I&Ǡ36~?Pa w8Pr.PwWFgOT3ɏ1 i5M\=fȦ[]oڑo/"F}F9mOCCN!и  ?X(>nH&p׋wt|% - y#;(8itb߷@!{7Ȋ@ YVvO@/{U MVi35'#WȯVeka^u˅nwU2?-ɿ[%;з$;mc fÀ(82 Tɪס2Zb,gTzuw11&o6F HjyZVLj~CRv/ t,t* M|k .TA5B=!&|,aRe1i%& !\1cr ^Iy p1 d>>̶Ոî 0rlqn/kءDVÈ9/ű1(x⤣2}o~X$Ū{s0a!-!)۳*)e\,0?Б\,ԩT _w:^VxV޾\!uQųåҶw#)Ei/z毲p[v F98/gsD)k)/Ifingӛ/~p%Q^$Slj>!DYܷ)eyCy9A+MWN )zkS< ~U3rŅ?~  ~tn,fy3jXDD1Zs"*ˁc8:$zi HIĀ@8HުL H_%A@N$A UeQr% 9jyMc@hV 틕Z Vqק)N-fcqw*7 5Wa"ɠBր[t!h!hl iwW~@PճMװx QV$AV ʔUWnྵa$ XK'aU{whkldMDfd~i/IO70j5,s@IvM;B(HDLns) _ɋ}oaOw.+rץ<}+FYYEEهTNoHm| ǥcs_DVj͈prͳ]ny` E`1©\1BN"r\,rN@%/N2g@#x\n܃"ukMxnXO DH?{vw#Vu*F_( +8=6 JRft;QZylu eX&hJpFS(l\v0k)h76*g$ k%ֿh,DUueI40" WIbuU~bڨv^FESGml,gHL|3ەCh\SU2` ߝWc9^28aI37~^b<#NygCHKJf-ۄoH Ja)Yfc(` 0qt&@3/C~A^ l( ؒ0~of˜os*`ژ46K-%#= %IH6Jo8C@TzWOpA:Z„TU|5YŗZ:G:%Sj~=eI&TwQ[P]vlDȨ!帊iX`[ŗY)L;]J5ULkD$5鰽bעT/I18T(q)9H[/u@g+3-fVo*ɛ`( ')dMP˲,\26K_A !PNhذy\CPIMAC8wn\e0Rԋ@+>`xT7}02m-yyS"wuXȃoxkcZ\3]ùzv٣Byqj3ƚ`'PC=+mvN%ύHf6AN( aϩI=߹_d: }+p?PO+Zbbyj.H@,Z@"ғ-ES4n)olIIBr~V>olbfLTq*+9)XLVRf.S9v.i硦>iFt+LVvuOx39]O#2]2=&K/~~<O^?vf)o=E4ӷ+4grN=U"g`k8=ü0}8QcÐӝXyTGָaYwSW-XVcNx.F~eyUڑ0@5㶼P?!@=LXI6QpӱڍyKoqK 0ݻ맕d5w$,ϩ/ tцB*v:-7ޚ, )p@ :$7ѴyN] h1 HZ޻Bf1畏?r 3uQB}\cmd!@ WS1zݨ]3CoFq"8ԚέiGb[UgfN G[oLĎnrWxzdD]Ջ` l_9 ]c2֋~ pIPӻߘ)* mS~H~X.t;/RG'~[!<8zvOB9`55'{ɸ6g {pqT3^-ZId, =4pBwbO&Ҹ$d%FN`7>͕xE_{ ۫v"{.1ן%$r_m L=mPO%os#(ĴyI%4aĘnzn|l6AT޾'VAJJ{` ,8I%vK$%Gv XY f 0NndQ& #PhꃢCAST part of OpenSSL 1.0.1c 10 May 2012AES part of OpenSSL 1.0.1c 10 May 2012aes(partial)(length%AES_BLOCK_SIZE) == 0(AES_ENCRYPT == enc)||(AES_DECRYPT == enc).\crypto\aes\aes_ige.cin && out && key && ivec)TPD ,$!%\QM@CCPQA< `cC#( (D@D  "%xsK;;.pp@0 <3?(0226tpD4, TSG\PLXSK=$ $ psC3 2, ,'prB2 ``@ PP@#+  6LCO7XRJxpH8&/`aA!4@AAPRB|qM=  PSC7!=trF6,#/$#'0 +"lbN.LAM haI)|pL<  ?/3>d`D$,".HCK   !!hcK+dbF&5 3|rN>xrJ:DCG%$"&-!000437.426 ""8084'DAEL@L )415 <0 <2><*:LBNTQE83 ;h`H(|sO?HBJ TRFtsG7 -DBF5(# +daE%:#91\RN9&2011*laM-\SO$0 82 :XPH`bB"(! )033( xqI9hbJ*(" *088(! -,&ܳ38/`@ `QET@DDcO/lcK+hSKXbB"`3305! )( "ࣇ'Б <264CK H/쀈`L,l(4AED!3?<1 =< ((BNL62><%9 # +(bF&drJ:x#'$#/,1rB2pBB@AA@sC3pcG'd, 7- ,,*044 .)QM\8SGT. ̂9?qM=|1105 bJ*h1 "" `H(hqA1pؑaA!`>&QIXQAPܒ#+Ё CGD #,쁍 ?sK;xPL\"!cC#`## AM LȒ2 :8 ".,:bN.lRJX23AI HpH8x ;p@0pqE5tsO?|154`D$daM-lpD4t԰4* rF6t >@@@ ్=:0" *(RN\)RFTCC@ 0%@HHqI9x<!!  SO\sG7tPDT2 !%$COLBFD-PHXRBP+rN>| =000aE%d0 <<6$䳋;pL<| P@P1 98"&$220aI)h374' $$$ SCP @L L3 ;8BJ H7)DTP ,%$!M\QC@CAPQ< C#`c(( DD@  "%K;xs;.@0pp ?<3(2026D4tp, GTSL\PKXS=$$ C3ps 2 ,, 'B2prц @ ``@PP#+ 6OLC7JXRH8xp&/A!`aÄ4A@ABPRM=|q  CPS7!=F6tr/,#'$#0  +"N.lbM LAI)haL<|p  ?/3>D$d`.,"K HC ! !K+hcF&db5 3N>|rJ:xrGDC%&$"-Ӂ!000743.642" "8804'EDAL L@)541  <<0A1pqÉ E5tq;8IXQ?I HA 981G'dcӈ8 B@B# #L,l`ӄ$4401HH@O/lc =<1 -,!@@@>><2<*:NLBETQ ;83H(h`O?|sJ HBFTRG7ts -FDB5 +(#E%da:#91N\R9&2101*M-laO\S$0  :82HXPB"`b )(!303( I9xqJ*hb *("880(-,! &38/ ``@TQED@D/lcO+hcKXSK"`bB3035)(! "' <642 HCK/,l`L(4DAE!?<3=<1 (( LBN6><2%9  +(# &dbF:xrJ'$#/,#12prB@BB@AA3psC'dcG, 7- ,, *440  .)\QM8TSG. 9?=|qM1015 *hbJ1 " "(h`H1pqA!`aA>&XQIPQA#+ DCG #, ?;xsK\PL"!#`cC# # LAM:82 .,":.lbNXRJ23 HAI8xpH ;0pp@5tqE?|sO541$d`D-laM4tpD4*  6trF >@@@ =:0*(" \RN)TRF@CC 0%H@H9xqI<! !  \SO7tsGTPD2 %$!LCODBF-XPHPRB+>|rN =000%daE<<0 6$;<|pL PP@981 &$"202)haI743'$$ $ PSC   L@L;83 HBJ7.\crypto\modes\gcm128.c.\crypto\bn\bn_add.c.\crypto\bn\bn_div.c.\crypto\bn\bn_exp.cBig Number part of OpenSSL 1.0.1c 10 May 20128m .\crypto\bn\bn_lib.c.\crypto\bn\bn_ctx.c.\crypto\bn\bn_mod.c0123456789ABCDEF.\crypto\bn\bn_print.c%09u%u0-bn(%d,%d).\crypto\bn\bn_rand.c.\crypto\bn\bn_blind.c.\crypto\bn\bn_sqrt.c.\crypto\bn\bn_gcd.c %)+/5;=CGIOSYaegkmq %379=KQ[]agou{  #-39;AKQWY_eikw)+57;=GUY[_mqsw %'-?CEIOU]ci  ')/QW]ew #+/=AGIMSU[ey '7EKOQUWamsy!#')3?AQSY]_iq   # % + / 5 C I M O U Y _ k q w   ! 1 9 = I W a c g o u {      # ) - ? G Q W ] e o {   % / 1 A [ _ a m s w      ! + - = ? O U i y !'/5;KWY]kqu}  %)1CGMOSY[gk!%+9=?Qisy{ '-9EGY_cio #)+17AGS_qsy} '-7CEIOW]gim{!/3;EMYkoqu %)+7=ACI_egk} %39=EOUimou #'3A]cw{57;CIMUgqw}13EIQ[y!#-/5?MQik{}#%/17;AGOUYeks '+-3=EKOUs !#59?AKS]ciqu{} %+/=IMOmq 9IKQgu{   ' ) - 3 G M Q _ c e i w } !!5!A!I!O!Y![!_!s!}!!!!!!!!!!!!!!!!!" """!"%"+"1"9"K"O"c"g"s"u"""""""""""""""# # #'#)#/#3#5#E#Q#S#Y#c#k################$ $$$)$=$A$C$M$_$g$k$y$}$$$$$$$$$$$$$$$$$$%%%%'%1%=%C%K%O%s%%%%%%%%%%%%%%%%& &&&'&)&5&;&?&K&S&Y&e&i&o&{&&&&&&&&&&&&&&&''5'7'M'S'U'_'k'm's'w''''''''''''''(( ((((!(1(=(?(I(Q([(](a(g(u((((((((((((()))!)#)?)G)])e)i)o)u))))))))))))))))***%*/*O*U*_*e*k*m*s***************+'+1+3+=+?+K+O+U+i+m+o+{++++++++++++++ ,,,#,/,5,9,A,W,Y,i,w,,,,,,,,,,,,,,,,---;-C-I-M-a-e-q-----------... ...%.-.3.7.9.?.W.[.o.y................/ / //'/)/A/E/K/M/Q/W/o/u/}///////////////0 0#0)070;0U0Y0[0g0q0y0}000000000000000001 11!1'1-191C1E1K1]1a1g1m1s11111111111111 2222)252Y2]2c2k2o2u2w2{22222222222222223%3+3/353A3G3[3_3g3k3s3y33333333333334444474E4U4W4c4i4m44444444444444 555-535;5A5Q5e5o5q5w5{5}555555555555555666#6165676;6M6O6S6Y6a6k6m6666666666667777?7E7I7O7]7a7u7777777777778 8!83858A8G8K8S8W8_8e8o8q8}8888888888888899#9%9)9/9=9A9M9[9k9y9}999999999999999999::::':+:1:K:Q:[:c:g:m:y::::::::::::;;;!;#;-;9;E;S;Y;_;q;{;;;;;;;;;;;;;;;;;;< <<<<)<5 >>>>#>)>/>3>A>W>c>e>w>>>>>>>>>>>>>>>> ? ?7?;?=?A?Y?_?e?g?y?}????????????@!@%@+@1@?@C@E@]@a@g@m@@@@@@@@@@@@@ A AAA!A3A5A;A?AYAeAkAwA{AAAAAAAAAAABBBB#B)B/BCBSBUB[BaBsB}BBBBBBBBBBBBBBCCC%C'C3C7C9COCWCiCCCCCCCCCCCCCCCCC D DD#D)D;D?DEDKDQDSDYDeDoDDDDDDDDDDDDDDEEE+E1EAEIESEUEaEwE}EEEEEEEEtoo many temporary variablestoo many iterationsp is not primeno solutionno inversenot initializednot a squareinvalid rangeinvalid lengthinput not reducedexpand on static bignum dataencoding errordiv by zerocalled with even modulusbignum too longbad reciprocalarg2 lt arg3BN_usubBN_rand_rangeBN_randBN_newBN_mpi2bnBN_mod_sqrtBN_mod_mul_reciprocalBN_mod_lshift_quickBN_mod_inverse_no_branchBN_mod_inverseBN_mod_exp_simpleBN_mod_exp_recpBN_mod_exp_mont_wordBN_mod_exp_mont_consttimeBN_mod_exp_montBN_mod_exp2_montBN_GF2m_mod_sqrtBN_GF2m_mod_sqrBN_GF2m_mod_solve_quad_arrBN_GF2m_mod_solve_quadBN_GF2m_mod_mulBN_GF2m_mod_expBN_GF2m_modBN_EXPAND_INTERNALbn_expand2BN_expBN_div_recpBN_div_no_branchBN_divBN_CTX_startBN_CTX_newBN_CTX_getBN_bn2hexBN_bn2decBN_BLINDING_updateBN_BLINDING_newBN_BLINDING_invert_exBN_BLINDING_create_paramBN_BLINDING_convert_exBNRAND.\crypto\bn\bn_recp.c.\crypto\bn\bn_mont.c.\crypto\bn\bn_mpi.c.\crypto\bn\bn_exp2.c@ADEPQTU.\crypto\bn\bn_gf2m.c p     @     h !!ڢ!h4b)Ngt ;"QJy4:C0+ m_7O5mmQE䅵vb^~LB:6 ڢ!h4b)Ngt ;"QJy4:C0+ m_7O5mmQE䅵vb^~LB7k \8kZ$|KI(fQSڢ!h4b)Ngt ;"QJy4:C0+ m_7O5mmQE䅵vb^~LB7k \8kZ$|KI(fQ[=|cH6UӚi?$_e]#ܣbV R)pmg 5NJtl#s'ڢ!h4b)Ngt ;"QJy4:C0+ m_7O5mmQE䅵vb^~LB7k \8kZ$|KI(fQ[=|cH6UӚi?$_e]#ܣbV R)pmg 5NJtl!|2^F.6;w,']oLR+X9I|j&rZhڢ!h4b)Ngt ;"QJy4:C0+ m_7O5mmQE䅵vb^~LB7k \8kZ$|KI(fQ[=|cH6UӚi?$_e]#ܣbV R)pmg 5NJtl!|2^F.6;w,']oLR+X9I|j&rZ-3 Pz3U!dX qW] }ǫ 3J%a&k/يdvs>jdR+{ Wza]lw FOt1C[K :ڢ!h4b)Ngt ;"QJy4:C0+ m_7O5mmQE䅵vb^~LB7k \8kZ$|KI(fQ[=|cH6UӚi?$_e]#ܣbV R)pmg 5NJtl!|2^F.6;w,']oLR+X9I|j&rZ-3 Pz3U!dX qW] }ǫ 3J%a&k/يdvs>jdR+{ Wza]lw FOt1C[K !r<׈q[&'j<h4 %*Lۻގ.ʦ(|YGNk]Oâ#;Q[a)pׯv!pH'հZ꘍ܐM541ڢ!h4b)Ngt ;"QJy4:C0+ m_7O5mmQE䅵vb^~LB7k \8kZ$|KI(fQ[=|cH6UӚi?$_e]#ܣbV R)pmg 5NJtl!|2^F.6;w,']oLR+X9I|j&rZ-3 Pz3U!dX qW] }ǫ 3J%a&k/يdvs>jdR+{ Wza]lw FOt1C[K !r<׈q[&'j<h4 %*Lۻގ.ʦ(|YGNk]Oâ#;Q[a)pׯv!pH'հZ꘍ܐM546|p&ܲ`&Fuv=7S8/A0jS'1'Z>ϛDlԻG%K3 QQ+ׯBo7ҿYK2rnt^p/F @1 Y#z~6̈EXZK+AT̏m~H^7ৗ(ՋvP=̱\V.28n<h>f?H`-[ ttm@$ڢ!h4b)Ngt ;"QJy4:C0+ m_7O5mmQE䅵vb^~LB7k \8kZ$|KI(fQ[=|cH6UӚi?$_e]#ܣbV R)pmg 5NJtl!|2^F.6;w,']oLR+X9I|j&rZ-3 Pz3U!dX qW] }ǫ 3J%a&k/يdvs>jdR+{ Wza]lw FOt1C[K !r<׈q[&'j<h4 %*Lۻގ.ʦ(|YGNk]Oâ#;Q[a)pׯv!pH'հZ꘍ܐM546|p&ܲ`&Fuv=7S8/A0jS'1'Z>ϛDlԻG%K3 QQ+ׯBo7ҿYK2rnt^p/F @1 Y#z~6̈EXZK+AT̏m~H^7ৗ(ՋvP=̱\V.28n<h>f?H`-[ ttmYto8w|2ߌؾs1;2tG%vk$f:cZh4#t+x#e-"".|W#4sdl0kKȆ/Kyh3[:+)E\\*=05jzjgszͬs1/>䘎k-nAPZV9.ѝ**慎"7 tn;bYAT*8U]U)l:T^8rv 6J&,o])(|1 `~zC|_cM7-X Hzj)sBО)Sg92dQ>a!@r[󸴉 V9Q~{R;5s߈=,4EkP?ƅ͞>f#Bd9?!(`kM=K^wY('3HjB~~1f9)jx;\_,}٘DIWDh'>f,r^&@P?a5ƶ"߹\k% cd 9:hSIxBwiɉrioHJetizg+*=}p_$܀AH1ihD5޳xĶ\Y*Wc."=9ZʧB=G`b%ki})wZx7X+J"8"cs73KIܶjmvHCzb1?B@;` uy`2}kl;ATuq/}7ya”, <ܨl3d+XW=?';<} ]n@TS FTh"k9{^]qR&  S;+˚ah2Wl $?XKzL/,8 ه'pQ !^&)jgh\HS`TP_Z扏9 U+"o;onl]A|'`Kk,BGc@w}-39Eؘ–OBJ|+3Wk1^˶@h7Qc%Q MinghuaQu)rx?|*b^fv |*b^fv e9މp+" Hr9Z^kU𘨜寇$>u|*b^v(߬eaŖ'WMinghuaQuS^ |*b^fv a'L \,Q]tL K 蒴dВCF.7Gnn6 ظY| K MinghuaQu :Ds6yuyy=$<,^R- (`|,[Z9[-zu 8MinghuaQu41;ѳY̛^),eXm]{j^W)2@'jM:q_KD?$rs;L8,zv06M~51k‚S3)E\\*=#֖vVVI0% dX &D#sao55b(0'yX1^9ov`֖vV]h~Z U){Կ6YOzj{&^/͸GNgL敺x$MinghuaQu[ӭ!:  kV!DA%pVKc)xAߘ3Ccn~sKNP1#:dM[ӭ֖vVZ!: 娉A_es&jFVWsL!VP1e-#fHmy@6m&]$iT3S{דNm^\]8X2.68ڣ ,OT(Fx*a-ܴ k)ʑ:XiCwVgVxzxvTC^BﯲQ Hœ' `SQ/xtJ2b~hԙF74>6lq OE\ ys$w #L3?MinghuaQuwű0zQiq{@ ȩ{Ièz[|1G_JtloaybSr%7: jJwD:̒I֖vVQ7ȡo"cZQ7>g >iwpɻ'L7~*j[Cٶ}.g~Q5 a~Δ3V)'"LlZVTr2:~s)/ck Lna&S}UZg'͛VV[nst՟kA=K4K Pfd~l3, #X!;3; B_}ˬ!9u_e96sqUj5x( g6qo~Rt/i"&ח@)s '&L{*eU05v1.T05u1*]ƷeS Zy|x$!?xD?;bS&_#Vzi¬$XI(681]Bo~EFYb6N4aw"Y.uw&]E1;y9%ݐOp.%U~;͆ SghT$Բ Qo5ݰgyE9`[*|ﭳ4`_eI:q! L'ϸ|`b".U@7Fi |NB)4`x/'2Qe_lBRzXcH(k_ @U}^[K\_ϗ4@W֟y!= LKMBb! !\Ku;{GkB.gGa֬'ȩr/lzUOP1{T_]H`ЈݳIk `dub`DJwM[4%ZQV`yNTyaϫk+$jv6ŧXOTЏ8QOKO@6ds֦3_|</d7٢sH%nY?1?䬜`$HCpG0MΰѺ9IGvGMʈRrI܀O7OJ;ʕ1MՌ0zTm,IyDOrܶ {20YL>ǣPc䳑ۑA80K98޴\wc|H*X:3Hka:#%~"!)q/\jˌkJY3+gVn)JZxRM9 )Urz4V)l CWbFS/Qn#<H'[aUsh#ݜ=Qtn/NGv`֖vVT%FCR4"xu2Ȕ5RBQ}$ <8K MoiF=y2=t3#!Yf?XHʟȂMSL D֖vVX wıف|Qrg8NH@t3O8 $&nNm MĆ&qۛlhMf%8#џM۷P\MinghuaQuj6&=>%ViTG*V8oHT%+{|WM ϊ"RGu޽5Y ^H?q=  n)\@}9Ж{pK ]G dގ3( †g`)JWoS-ֺ}a6+jV,SsW+ &NT'D֖vVU/'(fS{ggRcjheT&@'kdRbg.EWxogTb 62ײ67J v[43^3)2E$@Ðgȓq/$֖vVX\@(wMwwǷfmfC q'O ($+|їbj8 (Zj(xCCbm`!:>zC}f PPe($ksSQ-Ƅ֖vVPgxmlGV ""Vw~wwq&τyYc2?7]LOCDއFP n8&TZ9aW]Y6njL|{UUUUUUUUUUUa h(>HaZb!.`4+D9*?cߕYzxUN'ѥzU玚Ê_ ذa}\#{l!.-^Ոq~!/KMinghuaQuq ]2W|T1:FgVCB>'uxWxvy9/02| Ã"Wp.| [pnVk~|RaPw?k&itNqdǩac MBI*IfG*/ߤ֖vV]&g''}B0wWg#Vtc%Sf&dyVT_P7eA͂J/.?wREr/ͷK(NiG4vҹ1p LVg3LE;^,qbV}TSn"~3UUUUUUUUUUUUUUL# ;_JN"(q-Bu+,@ M͵ qg+|4*Up:o?̄@a,l b-w# qݍiWk.aBA0^ʰ^]ޝ#THn1rE{{b!'. i1IQ 7~_-Q Dt(x6ZۗU CyڦxyNqf@9`Us@{^j_<,z>\&(ZdOt &៾n qQ~@P(2RzAj^& T;VW*VW*-\?ahDC-L+5I $֖vVX[3-ƀVggjeK uO5n FV|FgUVVFg#VVTfVW$r|I6?]R}]E]94V&t+c)#<%wgy8A6j.:$ߜkޘz"9S)TpHy9HO{N#exhW-0Z@q(k򆼡(k򆼡(kkV, Oqtu;/p % R"%nyU [Gxv/ Q*j 2 E,v X0<4E87N I-dDGjuSUz‚VFųJ9Lk"'!oj_{>ܺbزRWs,Yb:E8C|хZڨ*P#Q-rIي]ǰS.Q;zy @1[g6`'~ #Llj]9[#lĭ,* ЕloaThM͏ٴ}CYTL놂7ژ*gZbmNPszb8&]j˰L/z}ᨛb]jY7`@4@4@4@4@4@4@4@4@4#p;^ƍ5 IJfyy pxKJcx\ms@3{LjІl  |D۟$ ^ ( 0    0    H     \ 8 4       (  X T  ,  , H               \  ( 0    P     x  x p P 8 $  $   h      `      X |  T  T h T  ,       `  H  H   d  <    (   `   (     8   x  x   x (   .\crypto\ec\ec_curve.c.\crypto\ec\ec_check.c0123456789ABCDEF.\crypto\ec\ec_print.cEC_PRIVATEKEYpublicKeyparametersprivateKeyECPKPARAMETERSvalue.implicitlyCAvalue.parametersvalue.named_curveECPARAMETERScofactororderbasecurvefieldIDX9_62_CURVEseedbaX9_62_FIELDIDfieldTypep.char_twop.primeX9_62_CHARACTERISTIC_TWOtypemp.ppBasisp.tpBasisp.onBasisp.otherX9_62_PENTANOMIALk3k2k1 @ @ @   0  t  h  \ X @P 4 x  4  ,       0      t    @ @         p  ` ` @ @T H  <   , .\crypto\ec\ec_asn1.c.\crypto\ec\ec_key.c@p0`P`0@@P0.\crypto\ec\ec2_smpl.c.\crypto\ec\ec2_mult.cOpenSSL EC algorithmEC< $ 0 P  p P @` p0   .\crypto\ec\ec_ameth.cECDSA-Parameters  0 P` `0.\crypto\ec\ec_pmeth.cec_paramgen_curveGenerator (hybrid):Generator (uncompressed):Generator (compressed):%02x%s.\crypto\ec\eck_prn.cSeed:Cofactor: Order: B: A: Prime:Polynomial:Basis Type: %s Field Type: %s ASN1 OID: %s.\crypto\ec\ecp_oct.c.\crypto\ec\ec2_oct.c.\crypto\ec\ec_oct.cECDH part of OpenSSL 1.0.1c 10 May 2012.\crypto\ecdh\ech_lib.cOpenSSL ECDH method.\crypto\ecdh\ech_ossl.cpoint arithmetic failureKDF failedECDH_DATA_new_methodECDH_compute_keyECDH_CHECKECDSA part of OpenSSL 1.0.1c 10 May 2012.\crypto\ecdsa\ecs_lib.cECDSA_SIG ? ?  OpenSSL ECDSA method.\crypto\ecdsa\ecs_ossl.csignature malloc failedrandom number generation failederr ec libECDSA_sign_setupECDSA_do_verifyECDSA_do_signECDSA_DATA_NEW_METHODECDSA_CHECK.\crypto\buffer\buffer.c.\crypto\buffer\buf_str.cBUF_strndupBUF_strdupBUF_MEM_newBUF_MEM_grow_cleanBUF_MEM_growBUF_memdup.\crypto\bio\bio_lib.c bio callback - unknown type (%d) ctrl return %ld puts return %ld gets return %ld write return %ld read return %ld ctrl(%lu) - %s gets(%lu) - %s puts() - %s write(%d,%lu) - %s write(%d,%lu) - %s fd=%d read(%d,%lu) - %s read(%d,%lu) - %s fd=%d Free - %s BIO[%08lX]:WSAStartupwrite to read only BIOunsupported methoduninitializedunable to listen socketunable to create socketunable to bind sockettag mismatchnull parameterno such fileno port specifiedno port definedno hostname specifiedno accept port specifiednbio connect errorkeepalivein useinvalid ip addressgethostbyname addr is not af ineterror setting nbio on accept socketerror setting nbio on accepted socketerror setting nbioEOF on memory BIOconnect errorbroken pipebad hostname lookupbad fopen modeaccept errorWSASTARTUPSSL_newMEM_WRITEMEM_READLINEBUFFER_CTRLFILE_READFILE_CTRLDGRAM_SCTP_READCONN_STATECONN_CTRLBUFFER_CTRLBIO_writeBIO_sock_initBIO_readBIO_putsBIO_nwrite0BIO_nwriteBIO_nread0BIO_nreadBIO_new_mem_bufBIO_new_fileBIO_newBIO_MAKE_PAIRBIO_get_portBIO_get_host_ipBIO_get_accept_socketBIO_getsBIO_gethostbynameBIO_ctrlBIO_callback_ctrlBIO_BER_GET_HEADERBIO_acceptACPT_STATEmemory buffer.\crypto\bio\bss_mem.cNULLfile descriptorFILE pointer.\crypto\bio\bss_file.cfopen('','')twr+a+socketsocket connecthost=.\crypto\bio\bss_conn.c%d%d.%d.%d.%dNULL filterbuffer.\crypto\bio\bf_buff.c$@?.\crypto\bio\b_print.c0123456789abcdef0xdoapr()%s%04x - %c %02x%c %04x - service=''gopherftphttpssockstelnethttptcp.\crypto\bio\b_sock.c%s:%s%d.%d.%d.%d:%dgetnameinfoport='*freeaddrinfogetaddrinfosocket accept.\crypto\bio\bss_acpt.cnon-blocking IO test filter.\crypto\bio\bf_nbio.cBIO pair.\crypto\bio\bss_bio.cdatagram socket.\crypto\bio\bss_dgram.csetsockoptgetsockoptStack part of OpenSSL 1.0.1c 10 May 2012.\crypto\stack\stack.clhash part of OpenSSL 1.0.1c 10 May 2012.\crypto\lhash\lhash.cnum_hash_comps = %lu num_retrieve_miss = %lu num_retrieve = %lu num_no_delete = %lu num_delete = %lu num_replace = %lu num_insert = %lu num_comp_calls = %lu num_hash_calls = %lu num_contract_reallocs = %lu num_contracts = %lu num_expand_reallocs = %lu num_expands = %lu num_alloc_nodes = %u num_nodes = %u num_items = %lu node %6u -> %3u load %d.%02d actual load %d.%02d %lu items %lu nodes used out of %u RAND part of OpenSSL 1.0.1c 10 May 2012@@.\crypto\rand\md_rand.cYou need to read the OpenSSL FAQ, http://www.openssl.org/support/faq.html....................rbwb.rndC:HOMERANDFILEPRNG not seededno fips random method seterror instantiating drbgerror initialising drbgSSLEAY_RAND_BYTESRAND_init_fipsRAND_get_rand_method.\crypto\rand\rand_win.cDISPLAY@"@@@Thread32NextThread32FirstProcess32NextProcess32FirstHeap32ListNextHeap32ListFirstHeap32NextHeap32FirstCloseToolhelp32Snapshot@GetQueueStatusGetCursorInfoGetForegroundWindowUSER32.DLLP@Intel Hardware Cryptographic Service ProviderCryptReleaseContextCryptGenRandomCryptAcquireContextW1@LanmanServerF@LanmanWorkstationNetApiBufferFreeNetStatisticsGetNETAPI32.DLLADVAPI32.DLL??called a function that was disabled at compile-timeinternal errorpassed a null parametercalled a function you should not callmalloc failurefatalmissing asn1 eosasn1 length mismatchexpecting an asn1 sequencebad get asn1 object callbad asn1 object headernested asn1 errorTS libOCSP libENGINE libDSO libRAND libPKCS12 libX509V3 libPKCS7 libBIO libSSL libEC libCRYPTO libCONF libASN1 libX509 libDSA libPEM libOBJ libBUF libEVP libDH libRSA libBN libsystem libfreadopendirWSAstartupacceptlistenbindioctlsocketconnectfopenHMAC routinesCMS routinesFIPS routinesOCSP routinesengine routinestime stamp routinesDSO support routinesrandom number generatorPKCS12 routinesX509 V3 routinesPKCS7 routinesBIO routinesSSL routineselliptic curve routinescommon libcrypto routinesconfiguration file routinesasn1 encoding routinesx509 certificate routinesdsa routinesPEM routinesobject identifier routinesmemory buffer routinesdigital envelope routinesDiffie-Hellman routinesrsa routinesbignum routinessystem libraryunknown libraryP ` p.\crypto\err\err.cint_err_get (err.c)int_thread_get (err.c)unknownNAerror:%08lX:%s:%s:%sreason(%lu)func(%lu)lib(%lu)%lu:%s:%s:%d:%s .\crypto\objects\o_names.crsaesOaepRSAES-OAEPaes-256-cbc-hmac-sha1AES-256-CBC-HMAC-SHA1aes-192-cbc-hmac-sha1AES-192-CBC-HMAC-SHA1aes-128-cbc-hmac-sha1AES-128-CBC-HMAC-SHA1rc4-hmac-md5RC4-HMAC-MD5aes-256-xtsAES-256-XTSaes-128-xtsAES-128-XTSrsassaPssRSASSA-PSSmgf1MGF1Any Extended Key UsageanyExtendedKeyUsageid-camellia256-wrapid-camellia192-wrapid-camellia128-wrapaes-256-ctrAES-256-CTRaes-192-ctrAES-192-CTRaes-128-ctrAES-128-CTRid-aes256-wrap-padaes-256-ccmid-aes256-CCMaes-256-gcmid-aes256-GCMid-aes192-wrap-padaes-192-ccmid-aes192-CCMaes-192-gcmid-aes192-GCMid-aes128-wrap-padaes-128-ccmid-aes128-CCMaes-128-gcmid-aes128-GCMcmacid-alg-PWRI-KEKdmdNamedeltaRevocationListsupportedAlgorithmshouseIdentifieruniqueMemberdistinguishedNameprotocolInformationenhancedSearchGuidecrossCertificatePaircertificateRevocationListauthorityRevocationListcACertificateuserCertificateuserPasswordseeAlsoroleOccupantownermembersupportedApplicationContextpresentationAddresspreferredDeliveryMethoddestinationIndicatorregisteredAddressinternationaliSDNNumberx121AddressfacsimileTelephoneNumberteletexTerminalIdentifiertelexNumbertelephoneNumberphysicalDeliveryOfficeNamepostOfficeBoxpostalAddressbusinessCategorysearchGuidePermanent Identifierid-on-permanentIdentifierX509v3 Freshest CRLfreshestCRLMicrosoft Local Key setLocalKeySethmacGOST R 3410-2001 Parameter Set Cryptocomid-GostR3410-2001-ParamSet-ccGOST R 34.11-94 with GOST R 34.10-2001 Cryptocomid-GostR3411-94-with-GostR3410-2001-ccGOST R 34.11-94 with GOST R 34.10-94 Cryptocomid-GostR3411-94-with-GostR3410-94-ccGOST 34.10-2001 Cryptocomgost2001ccGOST 34.10-94 Cryptocomgost94ccGOST 28147-89 Cryptocom ParamSetid-Gost28147-89-ccid-GostR3410-94-bBisid-GostR3410-94-bid-GostR3410-94-aBisid-GostR3410-94-aid-GostR3410-2001-CryptoPro-XchB-ParamSetid-GostR3410-2001-CryptoPro-XchA-ParamSetid-GostR3410-2001-CryptoPro-C-ParamSetid-GostR3410-2001-CryptoPro-B-ParamSetid-GostR3410-2001-CryptoPro-A-ParamSetid-GostR3410-2001-TestParamSetid-GostR3410-94-CryptoPro-XchC-ParamSetid-GostR3410-94-CryptoPro-XchB-ParamSetid-GostR3410-94-CryptoPro-XchA-ParamSetid-GostR3410-94-CryptoPro-D-ParamSetid-GostR3410-94-CryptoPro-C-ParamSetid-GostR3410-94-CryptoPro-B-ParamSetid-GostR3410-94-CryptoPro-A-ParamSetid-GostR3410-94-TestParamSetid-Gost28147-89-CryptoPro-RIC-1-ParamSetid-Gost28147-89-CryptoPro-Oscar-1-0-ParamSetid-Gost28147-89-CryptoPro-Oscar-1-1-ParamSetid-Gost28147-89-CryptoPro-D-ParamSetid-Gost28147-89-CryptoPro-C-ParamSetid-Gost28147-89-CryptoPro-B-ParamSetid-Gost28147-89-CryptoPro-A-ParamSetid-Gost28147-89-TestParamSetid-GostR3411-94-CryptoProParamSetid-GostR3411-94-TestParamSetid-Gost28147-89-None-KeyMeshingid-Gost28147-89-CryptoPro-KeyMeshingGOST R 34.10-94 DHid-GostR3410-94DHGOST R 34.10-2001 DHid-GostR3410-2001DHGOST R 34.11-94 PRFprf-gostr3411-94GOST 28147-89 MACgost-macgost89-cntGOST 28147-89gost89GOST R 34.10-94gost94GOST R 34.10-2001gost2001HMAC GOST 34.11-94id-HMACGostR3411-94GOST R 34.11-94md_gost94GOST R 34.11-94 with GOST R 34.10-94id-GostR3411-94-with-GostR3410-94GOST R 34.11-94 with GOST R 34.10-2001id-GostR3411-94-with-GostR3410-2001cryptocomcryptoprowhirlpooldsa_with_SHA256dsa_with_SHA224hmacWithSHA512hmacWithSHA384hmacWithSHA256hmacWithSHA224hmacWithMD5ecdsa-with-SHA512ecdsa-with-SHA384ecdsa-with-SHA256ecdsa-with-SHA224ecdsa-with-Specifiedecdsa-with-Recommendedid-aes256-wrapid-aes192-wrapid-aes128-wrapid-ct-asciiTextWithCRLFid-smime-ct-compressedDataCA RepositorycaRepositoryid-it-suppLangTagsDiffie-Hellman based MACid-DHBasedMacpassword based MACid-PasswordBasedMAChmac-sha1HMAC-SHA1hmac-md5HMAC-MD5seed-cfbSEED-CFBseed-ofbSEED-OFBseed-cbcSEED-CBCseed-ecbSEED-ECBkisaKISAX509v3 Certificate IssuercertificateIssuerX509v3 Issuing Distrubution PointissuingDistributionPointX509v3 Subject Directory AttributessubjectDirectoryAttributescamellia-256-ofbCAMELLIA-256-OFBcamellia-192-ofbCAMELLIA-192-OFBcamellia-128-ofbCAMELLIA-128-OFBcamellia-256-cfb8CAMELLIA-256-CFB8camellia-192-cfb8CAMELLIA-192-CFB8camellia-128-cfb8CAMELLIA-128-CFB8camellia-256-cfb1CAMELLIA-256-CFB1camellia-192-cfb1CAMELLIA-192-CFB1camellia-128-cfb1CAMELLIA-128-CFB1camellia-256-cfbCAMELLIA-256-CFBcamellia-192-cfbCAMELLIA-192-CFBcamellia-128-cfbCAMELLIA-128-CFBcamellia-256-ecbCAMELLIA-256-ECBcamellia-192-ecbCAMELLIA-192-ECBcamellia-128-ecbCAMELLIA-128-ECBcamellia-256-cbcCAMELLIA-256-CBCcamellia-192-cbcCAMELLIA-192-CBCcamellia-128-cbcCAMELLIA-128-CBCipsec4Oakley-EC2N-4ipsec3Oakley-EC2N-3X509v3 Inhibit Any PolicyinhibitAnyPolicyX509v3 Policy MappingspolicyMappingsX509v3 Any PolicyanyPolicywap-wsg-idm-ecid-wtls12wap-wsg-idm-ecid-wtls11wap-wsg-idm-ecid-wtls10wap-wsg-idm-ecid-wtls9wap-wsg-idm-ecid-wtls8wap-wsg-idm-ecid-wtls7wap-wsg-idm-ecid-wtls6wap-wsg-idm-ecid-wtls5wap-wsg-idm-ecid-wtls4wap-wsg-idm-ecid-wtls3wap-wsg-idm-ecid-wtls1sect571r1sect571k1sect409r1sect409k1sect283r1sect283k1sect239k1sect233r1sect233k1sect193r2sect193r1sect163r2sect163r1sect163k1sect131r2sect131r1sect113r2sect113r1secp521r1secp384r1secp256k1secp224r1secp224k1secp192k1secp160r2secp160r1secp160k1secp128r2secp128r1secp112r2secp112r1c2tnb431r1c2pnb368w1c2tnb359v1c2pnb304w1c2pnb272w1c2onb239v5c2onb239v4c2tnb239v3c2tnb239v2c2tnb239v1c2pnb208w1c2onb191v5c2onb191v4c2tnb191v3c2tnb191v2c2tnb191v1c2pnb176v1c2pnb163v3c2pnb163v2c2pnb163v1ppBasistpBasisonBasisid-characteristic-two-basiswap-wsgwapcerticom-arcidentified-organizationsha224SHA224sha512SHA512sha384SHA384sha256SHA256sha224WithRSAEncryptionRSA-SHA224sha512WithRSAEncryptionRSA-SHA512sha384WithRSAEncryptionRSA-SHA384sha256WithRSAEncryptionRSA-SHA256Independentid-ppl-independentX509v3 Name ConstraintsnameConstraintsInherit allid-ppl-inheritAllAny languageid-ppl-anyLanguageProxy Certificate InformationproxyCertInfoid-pplpostalCodestreetAddressstreetdes-ede3-cfb8DES-EDE3-CFB8des-ede3-cfb1DES-EDE3-CFB1des-cfb8DES-CFB8des-cfb1DES-CFB1aes-256-cfb8AES-256-CFB8aes-192-cfb8AES-192-CFB8aes-128-cfb8AES-128-CFB8aes-256-cfb1AES-256-CFB1aes-192-cfb1AES-192-CFB1aes-128-cfb1AES-128-CFB1Microsoft Universal Principal NamemsUPNMicrosoft SmartcardloginmsSmartcardLoginInternational Organizationsinternational-organizationsjoint-iso-itu-tJOINT-ISO-ITU-Titu-tITU-TrsaOAEPEncryptionSETdes-cdmfDES-CDMFset-brand-Novusset-brand-MasterCardset-brand-Visaset-brand-JCBset-brand-AmericanExpressset-brand-Dinersset-brand-IATA-ATAsecure device signaturesetAttr-SecDevSigICC or token signaturesetAttr-TokICCsigcleartext track 2setAttr-T2cleartxtencrypted track 2setAttr-T2Encgenerate cryptogramsetAttr-GenCryptgrmsetAttr-IssCap-SigsetAttr-IssCap-T2setAttr-IssCap-CVMsetAttr-Token-B0PrimesetAttr-Token-EMVset-addPolicyset-rootKeyThumbissuer capabilitiessetAttr-IssCapsetAttr-TokenTypepayment gateway capabilitiessetAttr-PGWYcapsetAttr-CertsetCext-IssuerCapabilitiessetCext-TokenTypesetCext-Track2DatasetCext-TokenIdentifiersetCext-PGWYcapabilitiessetCext-setQualfsetCext-setExtsetCext-tunnelingsetCext-cCertRequiredsetCext-merchDatasetCext-certTypesetCext-hashedRootset-policy-rootadditional verificationsetext-cvsetext-track2setext-pinAnysetext-pinSecuremerchant initiated authsetext-miAuthgeneric cryptogramsetext-genCryptsetct-BCIDistributionTBSsetct-CRLNotificationResTBSsetct-CRLNotificationTBSsetct-CertResTBEsetct-CertReqTBEXsetct-CertReqTBEsetct-RegFormReqTBEsetct-BatchAdminResTBEsetct-BatchAdminReqTBEsetct-CredRevResTBEsetct-CredRevReqTBEXsetct-CredRevReqTBEsetct-CredResTBEsetct-CredReqTBEXsetct-CredReqTBEsetct-CapRevResTBEsetct-CapRevReqTBEXsetct-CapRevReqTBEsetct-CapResTBEsetct-CapReqTBEXsetct-CapReqTBEsetct-AuthRevResTBEBsetct-AuthRevResTBEsetct-AuthRevReqTBEsetct-AcqCardCodeMsgTBEsetct-CapTokenTBEXsetct-CapTokenTBEsetct-AuthTokenTBEsetct-AuthResTBEXsetct-AuthResTBEsetct-AuthReqTBEsetct-PIUnsignedTBEsetct-PIDualSignedTBEsetct-ErrorTBSsetct-CertInqReqTBSsetct-CertResDatasetct-CertReqTBSsetct-CertReqDatasetct-RegFormResTBSsetct-MeAqCInitResTBSsetct-CardCInitResTBSsetct-BatchAdminResDatasetct-BatchAdminReqDatasetct-PCertResTBSsetct-PCertReqDatasetct-CredRevResDatasetct-CredRevReqTBSXsetct-CredRevReqTBSsetct-CredResDatasetct-CredReqTBSXsetct-CredReqTBSsetct-CapRevResDatasetct-CapRevReqTBSXsetct-CapRevReqTBSsetct-CapResDatasetct-CapReqTBSXsetct-CapReqTBSsetct-AuthRevResTBSsetct-AuthRevResDatasetct-AuthRevReqTBSsetct-AcqCardCodeMsgsetct-CapTokenTBSsetct-CapTokenDatasetct-AuthTokenTBSsetct-AuthResTBSXsetct-AuthResTBSsetct-AuthReqTBSsetct-PResDatasetct-PI-TBSsetct-PInitResDatasetct-CapTokenSeqsetct-AuthRevResBaggagesetct-AuthRevReqBaggagesetct-AuthResBaggagesetct-HODInputsetct-PIDataUnsignedsetct-PIDatasetct-PIsetct-OIDatasetct-PANOnlysetct-PANTokensetct-PANDataset-brandcertificate extensionsset-certExtset-policyset-attrmessage extensionsset-msgExtcontent typesset-ctypeSecure Electronic Transactionsid-setpseudonymgenerationQualifierid-hex-multipart-messageid-hex-partial-messagemime-mhs-bodiesmime-mhs-headingsMIME MHSmime-mhsx500UniqueIdentifierdocumentPublisheraudiodITRedirectpersonalSignaturesubtreeMaximumQualitysubtreeMinimumQualitysingleLevelQualitydSAQualitybuildingNamemailPreferenceOptionjanetMailboxorganizationalStatusfriendlyCountryNamepagerTelephoneNumbermobileTelephoneNumberpersonalTitlehomePostalAddressassociatedNameassociatedDomaincNAMERecordsOARecordnSRecordmXRecordpilotAttributeType27aRecordlastModifiedBylastModifiedTimeotherMailboxsecretaryhomeTelephoneNumberdocumentLocationdocumentAuthordocumentVersiondocumentTitledocumentIdentifiermanagerhostuserClassphotoroomNumberfavouriteDrinkinforfc822MailboxmailtextEncodedORAddressuserIdUIDqualityLabelledDatapilotDSApilotOrganizationsimpleSecurityObjectfriendlyCountrydomainRelatedObjectdNSDomainrFC822localPartdocumentSeriesroomdocumentaccountpilotPersonpilotObjectcaseIgnoreIA5StringSyntaxiA5StringSyntaxpilotGroupspilotObjectClasspilotAttributeSyntaxpilotAttributeTypepilotucldataHold Instruction RejectholdInstructionRejectHold Instruction Call IssuerholdInstructionCallIssuerHold Instruction NoneholdInstructionNoneHold Instruction CodeholdInstructionCodeaes-256-cfbAES-256-CFBaes-256-ofbAES-256-OFBaes-256-cbcAES-256-CBCaes-256-ecbAES-256-ECBaes-192-cfbAES-192-CFBaes-192-ofbAES-192-OFBaes-192-cbcAES-192-CBCaes-192-ecbAES-192-ECBaes-128-cfbAES-128-CFBaes-128-ofbAES-128-OFBaes-128-cbcAES-128-CBCaes-128-ecbAES-128-ECBMicrosoft CSP NameCSPNameecdsa-with-SHA1prime256v1prime239v3prime239v2prime239v1prime192v3prime192v2prime192v1id-ecPublicKeycharacteristic-two-fieldprime-fieldANSI X9.62ansi-X9-62X509v3 No Revocation AvailablenoRevAvailX509v3 AC TargetingtargetInformationX509v3 Policy ConstraintspolicyConstraintsroleid-aca-encAttrsSubject Information AccesssubjectInfoAccessac-proxyingmd4WithRSAEncryptionRSA-MD4clearanceSelected Attribute Typesselected-attribute-typesDomaindomaindomainComponentDCdcObjectdcobjectEnterprisesenterprisesMailSNMPv2snmpv2SecuritysecurityPrivateprivateExperimentalexperimentalManagementmgmtDirectorydirectoryianaIANAdodDODorgORGdirectory services - algorithmsX500algorithmsrsaSignaturealgorithmTrust RoottrustRootpathvalidExtended OCSP StatusextendedStatusOCSP Service LocatorserviceLocatorOCSP Archive CutoffarchiveCutoffOCSP No ChecknoCheckAcceptable OCSP ResponsesacceptableResponsesOCSP CRL IDCrlIDOCSP NonceNonceBasic OCSP ResponsebasicOCSPResponsead dvcsAD_DVCSAD Time Stampingad_timestampingid-cct-PKIResponseid-cct-PKIDataid-cct-crsid-qcs-pkixQCSyntax-v1id-aca-roleid-aca-groupid-aca-chargingIdentityid-aca-accessIdentityid-aca-authenticationInfoid-pda-countryOfResidenceid-pda-countryOfCitizenshipid-pda-genderid-pda-placeOfBirthid-pda-dateOfBirthid-on-personalDataid-cmc-confirmCertAcceptanceid-cmc-popLinkWitnessid-cmc-popLinkRandomid-cmc-queryPendingid-cmc-responseInfoid-cmc-regInfoid-cmc-revokeRequestid-cmc-getCRLid-cmc-getCertid-cmc-lraPOPWitnessid-cmc-decryptedPOPid-cmc-encryptedPOPid-cmc-addExtensionsid-cmc-recipientNonceid-cmc-senderNonceid-cmc-transactionIdid-cmc-dataReturnid-cmc-identityProofid-cmc-identificationid-cmc-statusInfoid-alg-dh-popid-alg-dh-sig-hmac-sha1id-alg-noSignatureid-alg-des40id-regInfo-certReqid-regInfo-utf8Pairsid-regCtrl-protocolEncrKeyid-regCtrl-oldCertIDid-regCtrl-pkiArchiveOptionsid-regCtrl-pkiPublicationInfoid-regCtrl-authenticatorid-regCtrl-regTokenid-regInfoid-regCtrlid-it-origPKIMessageid-it-confirmWaitTimeid-it-implicitConfirmid-it-revPassphraseid-it-keyPairParamRepid-it-keyPairParamReqid-it-subscriptionResponseid-it-subscriptionRequestid-it-unsupportedOIDsid-it-currentCRLid-it-caKeyUpdateInfoid-it-preferredSymmAlgid-it-encKeyPairTypesid-it-signKeyPairTypesid-it-caProtEncCertdvcsDVCSIPSec UseripsecUserIPSec TunnelipsecTunnelIPSec End SystemipsecEndSystemtextNoticesbgp-routerIdentifiersbgp-autonomousSysNumsbgp-ipAddrBlockaaControlsac-targetingac-auditEntityqcStatementsBiometric InfobiometricInfoid-mod-cmp2000id-mod-dvcsid-mod-ocspid-mod-timestamp-protocolid-mod-attribute-certid-mod-qualified-cert-93id-mod-qualified-cert-88id-mod-cmpid-mod-kea-profile-93id-mod-kea-profile-88id-mod-cmcid-mod-crmfid-pkix1-implicit-93id-pkix1-explicit-93id-pkix1-implicit-88id-pkix1-explicit-88id-cctid-qcsid-acaid-pdaid-onid-cmcid-algid-pkipid-itid-qtid-pkix-modmd4MD4id-smime-cti-ets-proofOfCreationid-smime-cti-ets-proofOfApprovalid-smime-cti-ets-proofOfSenderid-smime-cti-ets-proofOfDeliveryid-smime-cti-ets-proofOfReceiptid-smime-cti-ets-proofOfOriginid-smime-spq-ets-sqt-unoticeid-smime-spq-ets-sqt-uriid-smime-cd-ldapid-smime-alg-CMSRC2wrapid-smime-alg-CMS3DESwrapid-smime-alg-ESDHid-smime-alg-RC2wrapid-smime-alg-3DESwrapid-smime-alg-ESDHwithRC2id-smime-alg-ESDHwith3DESid-smime-aa-dvcs-dvcid-smime-aa-signatureTypeid-smime-aa-ets-archiveTimeStampid-smime-aa-ets-certCRLTimestampid-smime-aa-ets-escTimeStampid-smime-aa-ets-revocationValuesid-smime-aa-ets-certValuesid-smime-aa-ets-RevocationRefsid-smime-aa-ets-CertificateRefsid-smime-aa-ets-contentTimestampid-smime-aa-ets-otherSigCertid-smime-aa-ets-signerAttrid-smime-aa-ets-signerLocationid-smime-aa-ets-commitmentTypeid-smime-aa-ets-sigPolicyIdid-smime-aa-timeStampTokenid-smime-aa-smimeEncryptCertsid-smime-aa-signingCertificateid-smime-aa-encrypKeyPrefid-smime-aa-contentReferenceid-smime-aa-equivalentLabelsid-smime-aa-macValueid-smime-aa-contentIdentifierid-smime-aa-encapContentTypeid-smime-aa-msgSigDigestid-smime-aa-contentHintid-smime-aa-mlExpandHistoryid-smime-aa-securityLabelid-smime-aa-receiptRequestid-smime-ct-DVCSResponseDataid-smime-ct-DVCSRequestDataid-smime-ct-contentInfoid-smime-ct-TDTInfoid-smime-ct-TSTInfoid-smime-ct-publishCertid-smime-ct-authDataid-smime-ct-receiptid-smime-mod-ets-eSigPolicy-97id-smime-mod-ets-eSigPolicy-88id-smime-mod-ets-eSignature-97id-smime-mod-ets-eSignature-88id-smime-mod-msg-v3id-smime-mod-oidid-smime-mod-essid-smime-mod-cmsid-smime-ctiid-smime-spqid-smime-cdid-smime-algid-smime-aaid-smime-ctid-smime-modS/MIMESMIMEpkcs5X9.57 CM ?X9cmX9.57X9-57ISO US Member BodyISO-USISO Member Bodymember-bodyisoISOOCSP SigningOCSPSigningCA IssuerscaIssuersOCSPAuthority Information AccessauthorityInfoAccessid-adid-pednQualifiernameExtension RequestextReqMicrosoft Extension RequestmsExtReqpbeWithSHA1AndDES-CBCPBE-SHA1-DESpbeWithMD5AndRC2-CBCPBE-MD5-RC2-64pbeWithMD2AndRC2-CBCPBE-MD2-RC2-64S/MIME CapabilitiesSMIME-CAPSrc2-64-cbcRC2-64-CBCPolicy Qualifier User Noticeid-qt-unoticePolicy Qualifier CPSid-qt-cpshmacWithSHA1PBMAC1PBES2x509CrlsdsiCertificatex509CertificatelocalKeyIDfriendlyNamesafeContentsBagsecretBagcrlBagcertBagpkcs8ShroudedKeyBagkeyBagpbeWithSHA1And40BitRC2-CBCPBE-SHA1-RC2-40pbeWithSHA1And128BitRC2-CBCPBE-SHA1-RC2-128pbeWithSHA1And2-KeyTripleDES-CBCPBE-SHA1-2DESpbeWithSHA1And3-KeyTripleDES-CBCPBE-SHA1-3DESpbeWithSHA1And40BitRC4PBE-SHA1-RC4-40pbeWithSHA1And128BitRC4PBE-SHA1-RC4-128Strong Extranet IDSXNetIDInvalidity DateinvalidityDateX509v3 CRL Reason CodeCRLReasonX509v3 Delta CRL IndicatordeltaCRLNetscape Server Gated CryptonsSGCMicrosoft Encrypted File SystemmsEFSMicrosoft Server Gated CryptomsSGCMicrosoft Trust List SigningmsCTLSignMicrosoft Commercial Code SigningmsCodeComMicrosoft Individual Code SigningmsCodeIndTime StampingtimeStampingE-mail ProtectionemailProtectionCode SigningcodeSigningTLS Web Client AuthenticationclientAuthTLS Web Server AuthenticationserverAuthid-kpPKIXX509v3 Extended Key UsageextendedKeyUsagezlib compressionZLIBrun length compressionRLErc5-ofbRC5-OFBrc5-cfbRC5-CFBrc5-ecbRC5-ECBrc5-cbcRC5-CBCripemd160WithRSARSA-RIPEMD160ripemd160RIPEMD160dsaEncryptionsha1WithRSARSA-SHA1-2md5-sha1MD5-SHA1dsaWithSHA1DSA-SHA1pbeWithMD5AndCast5CBCcast5-ofbCAST5-OFBcast5-cfbCAST5-CFBcast5-ecbCAST5-ECBcast5-cbcCAST5-CBCdescriptiontitleserialNumbermd5WithRSARSA-NP-MD5X509v3 CRL Distribution PointscrlDistributionPointsinitialssurnameSNgivenNameGNrc2-40-cbcRC2-40-CBCrc4-40RC4-40mdc2WithRSARSA-MDC2mdc2MDC2bf-ofbBF-OFBbf-cfbBF-CFBbf-ecbBF-ECBbf-cbcBF-CBCX509v3 Authority Key IdentifierauthorityKeyIdentifierX509v3 Certificate PoliciescertificatePoliciesX509v3 CRL NumbercrlNumberX509v3 Basic ConstraintsbasicConstraintsX509v3 Issuer Alternative NameissuerAltNameX509v3 Subject Alternative NamesubjectAltNameX509v3 Private Key Usage PeriodprivateKeyUsagePeriodX509v3 Key UsagekeyUsageX509v3 Subject Key IdentifiersubjectKeyIdentifierid-cedesx-cbcDESX-CBCNetscape Certificate SequencensCertSequenceNetscape CommentnsCommentNetscape SSL Server NamensSslServerNameNetscape CA Policy UrlnsCaPolicyUrlNetscape Renewal UrlnsRenewalUrlNetscape CA Revocation UrlnsCaRevocationUrlNetscape Revocation UrlnsRevocationUrlNetscape Base UrlnsBaseUrlNetscape Cert TypensCertTypedsaWithSHA1-oldDSA-SHA1-oldPBKDF2pbeWithSHA1AndRC2-CBCPBE-SHA1-RC2-64dsaEncryption-oldDSA-olddsaWithSHADSA-SHAsha1WithRSAEncryptionRSA-SHA1sha1SHA1des-ede3-ofbDES-EDE3-OFBdes-ede-ofbDES-EDE-OFBdes-ede3-cfbDES-EDE3-CFBdes-ede-cfbDES-EDE-CFBNetscape Data TypensDataTypeNetscape Certificate ExtensionnsCertExtNetscape Communications Corp.NetscapeextendedCertificateAttributesunstructuredAddresschallengePasswordcountersignaturesigningTimemessageDigestcontentTypeunstructuredNameemailAddresspkcs9idea-ofbIDEA-OFBdes-ofbDES-OFBdes-ede3-cbcDES-EDE3-CBCdes-ede-cbcDES-EDE-CBCshaWithRSAEncryptionRSA-SHAshaSHArc2-ofbRC2-OFBrc2-cfbRC2-CFBrc2-ecbRC2-ECBrc2-cbcRC2-CBCidea-ecbIDEA-ECBidea-cfbIDEA-CFBidea-cbcIDEA-CBCdes-ede3DES-EDE3des-edeDES-EDEdes-cbcDES-CBCdes-cfbDES-CFBdes-ecbDES-ECBdhKeyAgreementpkcs3pkcs7-encryptedDatapkcs7-digestDatapkcs7-signedAndEnvelopedDatapkcs7-envelopedDatapkcs7-signedDatapkcs7-datapkcs7organizationalUnitNameOUorganizationNameOstateOrProvinceNameSTlocalityNameLcountryNameCcommonNameCNX509directory services (X.500)X500pbeWithMD5AndDES-CBCPBE-MD5-DESpbeWithMD2AndDES-CBCPBE-MD2-DESmd5WithRSAEncryptionRSA-MD5md2WithRSAEncryptionRSA-MD2rsaEncryptionrc4RC4md5MD5md2MD2RSA Data Security, Inc. PKCSpkcsRSA Data Security, Inc.rsadsiundefinedUNDEF*H *H *H *H *H *H *H *H *H *H UUUUUUU U U*H *H *H *H *H *H *H *H *H ++ +++<*H ++*H +*H  *H  *H  *H  *H  *H  *H  *H  *H  *H  `HB`HB`HB+*H + + *H  *H  +`HB`HB`HB`HB`HB`HB`HB `HB `HBUUUUUUUUU U#+UUeUdU*UU+U+UU U *H}B *H}B *H8+*H8+$+$*H )*H  U%++++++++7+7+7 +7 +7 `HBUUU+e*H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H *H ++*H  *H *H *H  +7*H  U)U.++0++0+0+ (**H*H8*H8*H *H *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H   *H   *H   *H   *H   *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H  *H ++++++++ + + + +++++++++ + + + + +++++++++++ +++++ +++++++++ + + + + +++++++++++++++++++++++++ + + +++++++++++ + + + + + + + + + + + + + +0+0+0+0+0+0+0+0+0+0+0 +0 +0 ++ U++++++++++++:X &,d &,d UU7*H + + + UHU$U7U8*H=*H=*H=*H=*H=*H=*H=*H=*H=*H=*H=*H=+7`He`He`He`He`He`He`He`He`He)`He*`He+`He,U*H8*H8*H8 & &, &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d &,d% &,d& &,d' &,d( &,d) &,d* &,d+ &,d- &,d. &,d/ &,d0 &,d1 &,d2 &,d3 &,d4 &,d5 &,d6 &,d7 &,d8U-+++++U,UAg*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g* g* g* g* g* g*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g* g*!g*"g*#g*$g*%g*&g*'g*(g*)g**g*+g*,g*-g*.g*/g*0g*1g*2g*3g*4g*5g*6g*7g*8g*9g*:g*;g*g*?g*@g*Ag*Bg*Cg*Dg*Eg*Fg*Gg*Hg*Ig*Jg*Kg*Lg*Mg*Ng*Og*Pg*Qg*Rg*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g* g* g* g*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g*"g*#g*g*g*{*H  *H Pg+7+7U U++++U+*H  *H  *H  *H `He`He`He`He++g+g+*H=*H=*H=*H=*H=*H=*H=*H=*H=*H=*H=*H=*H= *H= *H= *H= *H= *H=*H=*H=*H=*H=*H=*H=+++++ ++++ +!+ +"+#+++++++++++++++$+%+&+'g+g+g+g+g+g+g+g+ g+ g+ g+ U U!U6*K=*K=*K=1 1 1 )1 1 1 ,1 1 1 +U UU*D*D*D*D*D++*H}B *H}B++0*H   *H  `He`He`He-*H=*H=*H=*H=*H=*H=*H *H *H  *H  *H  `He`He(7** *** * ******b*c************* * * * * *!*!*!*#*#*#*#*$*$***** * * * * * +7U.+UUUUUUUUUUUUUUUUUU U!U"U#U$U%U&U'U(U/U0U1U2U3U4U5U6*H   `He`He`He`He`He`He`He.`He/`He0*K=*K=*K=U%*H *H  *H  x  p X  P 0  , (  $            ~   ~ ~   ~ ~   ~ ~   x~ \~   T~ T~   P~ D~   @~ 4~  0~  ~  ~ ~  ~ }  } }   `  } }  } }   } }  } }   x} x}   d} d}  ( P} P}  1 H} H} : 8} 8}  B 0} (} K  } } P } } U } |  Z | | !| | " _ | | #| | $| | %j | x| &p| h| '`| X| (T| P| )r H| 0| *w $| | +| { ,| { { - { { .{ { / { { 0 { { 1 { { 2 { { 3 |{ |{ 4 h{ h{ 5 T{ T{ 6 ǀ @{ @{ 7 Ѐ  {  { 8 ـ { z 9 z z : z z ; z z <z pz =dz Xz >Hz 8z ?0z (z @ z z A y y B y y C y y D  y y E  y y F# xy dy G ( Xy Dy H 1 4y y I : y x J C x x K L x x L U x px M ^ dx Px N g @x  x O p x x Px x Qy w w R{ w w S~ w pw T `w @w U 0w w V v v W v v X v v Y xv Xv Z Pv Hv [ @v 8v \0v (v ] v v ^v v _ u u ` u u au u bu u c u u d u u e u hu g \u Pu h @u @u i 8u 8u j ,u ,u k  u u l u t mt t nt t ot t p ʁ t t qӁ t t rxt lt sځ  \t t߁ Pt Dt u 4t  t w t t x t t ys s zs s {s s | s s } s xs ~ ps ps  hs hs  \s  a a ? ň ` ` @ Έ ` ` A ׈ ` ` B ` ` C ` ` D ` ` E ` ` F l` l` G T` T` H <` <` I (` (` J! ` ` K) _ _ L1 _ _ M9 _ _ NA _ _ OI _ _ PQ _ _ QY |_ |_ Ra l_ l_ Si T_ T_ Tq D_ D_ Uy 0_ 0_ V _ _ W _ _ X ^ ^ Y ^ ^ Z ^ ^ [ ^ ^ \ ^ ^ ] ^ ^ _ d^ d^ `ɉ H^ H^ aщ ,^ ,^ bى ^ ^ c ] ] d ] ] e ] ] f ] ] g ] ] h ] ] i ] ] j ] t] k! l] d] l) P] <] m 1 4] (] n :  ] ] o C ] \ p L \ \ q U \ \ r ^ \ \ s g p\ X\ t p P\ P\ u y H\ H\ v <\ 0\ w $\ $\ x \ \ y \ [ z [ [ { [ [ | [ [ } [ [ ~ [ [  [ x[  p[ h[  \[ P[  H[ @[  8[ 8[  ,[  [  [ [  Ɗ [ Z  ϊ Z Z  ي    Z Z  Z Z  Z Z  tZ tZ  `Z DZ  4Z 4Z  ,Z ,Z  Z Y  Y Y  Y Y     Y Y  Y Y  hY hY % XY XY , LY LY 3 @Y @Y ; 4Y 4Y C (Y (Y K Y Y S Y Y [ Y Y c X X k X X  r X X  { X X  X X  X xX  lX `X  TX HX   0S 0S  H S S  R S S  \ R R  f R R  p R R  z R R  R R  R R  R R  lR lR  \R \R  DR DR  (R (R  R R  R R  R Q  Q Q Ž Q Q Ŏ Q Q Ȏ Q Q ˎ Q hQ Ύ \Q \Q ю LQ LQ Ԏ  L L ? L L @ L L A L L B L L Cď |L |L Dȏ hL hL Ȅ XL XL FЏ DL DL Gԏ 0L 0L H؏ L L I܏ L L J K K K K K L K K M K K N K K O K K P pK pK Q \K \K R HK HK S 4K 4K T  K  K U K K V J J W J J X J J Y J J Z lJ lJ [$ \J \J \( LJ LJ ], @J (J ^0 J J _4 J J `8 I I a< I I b@ I I cD I I dH I I eL I I fP pI pI gT XI XI hX DI DI i\ 0I 0I j` I I kd I I lh H H ml H H np H H ot H H px xH xH q} dH dH r LH LH s 8H 8H t $H $H u H H v G G w G G x G G y G pG z \G DG { 0G 0G | G G } G G ~ F F Ő F F ɐ F F ͐ F F ѐ F F ֐ F F  ސ F xF  hF XF   >  > >  > >  > x> h> `> L> 8>   $> >  ) = =  4 = = ? = = G = p= O \= H= W 4=  = _  = < g < < < < < < l< X< D< 0< < < ; ; o ; ; w ; ;  t; P;  4; ;  : :  : :  : :  : :   : :   |: p:   d: X:   L: @:   ,: :  Ɠ : 9  ϓ 9 9 ؓ 9 9  9 9  9 9  t9 t9  d9 d9   T9 T9   <9 <9  $9 $9  9 9 ' 8 8 / 8 8 7 8 8 ? 8 8 G 8 8 O 8 8 W 8 8  _ 8 8 !g x8 x8 " o h8 h8 # x \8 \8 $ P8 P8 % D8 D8 &  8 7 ' 7 7 ( 7 7 ) |7 h7 * \7 H7 + @7 07 , (7 7 -  7  7 .7 6 / 6 6 0 6 6 1ǔ 6 p6 2͔ H6 H6 3Ӕ (6 (6 4ڔ 6 6 5 5 5 6 5 5 7 5 5 8 t5 t5 9 L5 L5 : $5 $5 ; 4 4 < 4 4 = 4 4 > x4 x4 ?' P4 P4 @. (4 (4 A5 4 4 B< 3 3 CC 3 3 DJ 3 3 EQ `3 `3 FX @3 @3 G_ 3 3 Hf 2 2 Im 2 2 Jt 2 2 K{ p2 p2 L \2 \2 M D2 D2 N 02 02 O 2 2 P 2 1 Q 1 1 R 1 1 S l1 <1 T 1 0 Uŕ 0 0 V͕ 4 0 W0 h0 X Օ \0 H0 Yޕ ,0 0 Z 0 0 [ / / \ / / ] / / ^ / / _ / / ` / / a / / b d/ d/ c X/ X/ d @/ @/ e ,/ ,/ f / / g . . h . . i . . j . . k . . l . . m . . n" . . o% . . p( t. t. q+ \. \. r. @. @. s1 (. (. t4 . . u7 . . v: - - w= - - x@ - - yC - - zF - - {I - - |L - - } O  - ~t- h-  Z X- L-  c 8- 8-  l (- -  u  - -  ~ , ,  , ,  , ,  , ,  , , |, p, d, X, D, D,  0, 0,  , ,  , + ̖ + +  Ж + +  ٖ + + + + + x+ `+ H+ 0+ + + * * *  l[]\^lnmo~ o +<>!,=?-P|tBqFC)cW  }"#$.Xr_9n{ DEb%'&(axzy{u|`hw*As   )@d z }! pkxrZrWm\qYs625gXt&%{kg~w|"#0u8~tcY/+S-.,R !y89:;3=<>47QHIJKLVG1@ABCDEF?MNOP265'U(T* cbdef}CFED ijhQNZJPOSRHIQXYWMUVTLGK.*7/,6438-5+120Z[ `a\_]  g9<?>=@;:BAee&'(VS)k3qHLJ:OGN;KIMlvp_/^]hi0Tvfmy#"$[nisq~}|_plwotvum{xyzsrnkghjica`befd@:;<ABC=X.P/QWVDE !"FGH#$%I>?063ST45UJK&'(LMN)*+O71  ,-   89R2^YZ\[]4URzj`ba%jwx71pou$dkpm~t-Q/SR+1,2)0'U(TV*z&'(XHLJG:ON9;KIMroqnsEZw ZWgXY~YVSTUR! l^xr[]\^\qlnmos6y~ 25t&%{ +<>!,=?-kgP zw||tCBqF"#)0xu8cwYc.W   !y}89:;3=<>47HIJKLG@ABCDEF?MNOP65 cbdef}CFED ijhQNZJPOSRHIQXYWMUVTLGK.*7/,6438-5+120[ `a\_]  g9<?>=@;:BA"#$.eeorh_`kZ3{lvm p D_/^]hivb%'&(axzy{fuwmy|#"$[{n   iq~}|_pltvusrnkghjica`befd@:;<ABC=X.P/QWVDE !"FGH#$%I>?063ST45UJK&'(LMN)*+O71  ,-   89R2\[])@sA*4zjd`ba%jx71pou$d}{ | zQ} dijk[\]^_`abcdefghijklmnopqrstceuvwxyz{|RSTUVWXgYZ~Y~x`_      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^lmno_`abcdefghijk|}~%&h-yCB* )@Fsupqrstuv$|'()*+,-/012wwxyz{43MNOP56789:;<=>?@ABCDEFGHIJKLtq    9   TURSQV/ !%,x  !"#$%&'()*+,-./0123456789:CDEFGHIJKLMNOPQRSTUVWXYZ[Z\]_`abcdefghijkl  :;lpA DE012345678X[;<=>?@ABmnopqrstuvw"#GHIJKLMNO}}".\crypto\objects\obj_dat.c.%lu.\crypto\objects\obj_lib.cunknown nidOBJ_nid2snOBJ_nid2objOBJ_nid2lnOBJ_NAME_new_indexOBJ_dupOBJ_createOBJ_add_object*)A@B)tF@C`_hq@ts@wu@"t#t')+(),T)RU)S,$< 0`HTlx .\crypto\objects\obj_xref.cABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/>?456789:;<=  !"#$%&'()*+,-./0123.\crypto\evp\encode.cctx->length <= (int)sizeof(ctx->enc_data)n < (int)sizeof(ctx->enc_data).\crypto\evp\digest.cctx->digest->md_size <= EVP_MAX_MD_SIZEEVP part of OpenSSL 1.0.1c 10 May 2012.\crypto\evp\evp_enc.cbl <= (int)sizeof(ctx->buf)b <= sizeof ctx->bufb <= sizeof ctx->finalEVP_CIPHER_CTX_iv_length(ctx) <= (int)sizeof(ctx->iv)ctx->cipher->block_size == 1 || ctx->cipher->block_size == 8 || ctx->cipher->block_size == 16niv <= EVP_MAX_IV_LENGTH.\crypto\evp\evp_key.cnkey <= EVP_MAX_KEY_LENGTH0B ? PB0B? PB-0B> PB0B@> PB0B0@ PB0B@A PB[ DBH ] DCH ^ DCH \ DpCH "FE #FF .FE $FD +K`H L<KH L>KG L K`G L,K`H L=KH L?KG L!K`G LKI LKPJ L@PL @PM @P@N @P`M @PL @PM @P@N @P`M  @PL  @PM  @P@N  @P`M @P O @P O  @P O @PO @PO  @PO .\crypto\evp\e_camellia.cPPaPPPQQPTUPQRPT0VPQVPTVPQVPTV@QPW@TPW@QW@TW@Q0X@T0XPQQPTUPQRPT0VPQVPTVPQVPTV@QPW@TPW@QW@TW@Q0X@T0X PQQ PTU PQR PT0V PQV PTV PQV PTV @QPW @TPW @QW @TW @Q0X @T0X vP0@Ra`[[ vP00_a`[[ vP0@Ra`[[ vP00_a`[[ vP0@Ra`[[ vP00_a`[[ qP0Sdpc qPcdpc@qP0Sdpc@qPcdpc wPThHe wP0ghHe wPThHe wP0ghHe wPThHe wP0ghHe.\crypto\evp\e_aes.c `o`m `om `on`o@nPoo %Jrptst'Krqtst(Lrqtst&IrqtstJrptstbJrptst.\crypto\evp\e_rc2.cl <= sizeof(iv)l @w@u n @wu o @wv m @w v www`@`www`@`)*yx x`@d@A yy `@d `xxx`@t pxxx`@t0 xxy`@ xxy`$@@yPy`y@BByy PtBqF@dtqyy PtBqF@d_`yyy$uwy z0z`@dyy  CC@d.\crypto\evp\p_open.c.\crypto\evp\p_sign.c.\crypto\evp\p_verify.c.\crypto\evp\p_lib.c%s algorithm "%s" unsupported Public KeyPrivate KeyParameters.\crypto\evp\p_enc.c.\crypto\evp\p_dec.cmessage digestbase64 encoding.\crypto\evp\bio_b64.cctx->buf_off+i < (int)sizeof(ctx->buf)ctx->buf_len >= ctx->buf_offctx->tmp_len <= 3ctx->buf_off <= (int)sizeof(ctx->buf)i <= nctx->buf_len <= (int)sizeof(ctx->buf)ctx->buf_off < (int)sizeof(ctx->buf).\crypto\evp\bio_enc.cwrong public key typewrong final block lengthunsupported salt typeunsupported private key algorithmunsupported prfunsupported key sizeunsupported key derivation functionunsupported keylengthunsupported cipherunsupported algorithmunsuported number of roundsunknown pbe algorithmunknown digestunknown ciphertoo largepublic key not rsaprivate key encode errorprivate key decode errorpkcs8 unknown broken typeoperaton not initializedno verify function configuredno sign function configuredno operation setno key setno dsa parametersno digest setno default digestno cipher setmethod not supportedmessage digest is nullkeygen failureiv too largeinvalid operationinvalid key lengthinvalid digestinput not initializedinitialization errorexpecting a ec keyexpecting a ecdsa keyexpecting a dsa keyexpecting a dh keyexpecting an rsa keyevp pbe cipherinit errorencode errordisabled for fipsdifferent parametersdifferent key typesdata not multiple of block lengthctrl operation not implementedctrl not implementedcommand not supportedcipher parameter errorcamellia key setup failedbn pubkey errorbad key lengthbad decryptbad block lengthasn1 libaes key setup failedaes iv setup failedRC5_CTRLRC2_MAGIC_TO_METHPKEY_SET_TYPEPKCS8_set_brokenPKCS5_V2_PBKDF2_KEYIVGENPKCS5_v2_PBE_keyivgenPKCS5_PBE_keyivgenINT_CTX_NEWHMAC_Init_exFIPS_MD_CTX_COPYFIPS_DIGESTINITFIPS_CIPHER_CTX_SET_KEY_LENGTHFIPS_CIPHER_CTX_CTRLFIPS_CIPHER_CTX_COPYFIPS_CIPHERINITEVP_VerifyFinalEVP_SignFinalEVP_RIJNDAELEVP_PKEY_verify_recover_initEVP_PKEY_verify_recoverEVP_PKEY_verify_initEVP_PKEY_verifyEVP_PKEY_sign_initEVP_PKEY_signEVP_PKEY_paramgen_initEVP_PKEY_paramgenEVP_PKEY_newEVP_PKEY_keygen_initEVP_PKEY_keygenEVP_PKEY_get1_RSAEVP_PKEY_get1_EC_KEYEVP_PKEY_GET1_ECDSAEVP_PKEY_get1_DSAEVP_PKEY_get1_DHEVP_PKEY_encrypt_oldEVP_PKEY_encrypt_initEVP_PKEY_encryptEVP_PKEY_derive_set_peerEVP_PKEY_derive_initEVP_PKEY_deriveEVP_PKEY_decrypt_oldEVP_PKEY_decrypt_initEVP_PKEY_decryptEVP_PKEY_CTX_dupEVP_PKEY_CTX_ctrl_strEVP_PKEY_CTX_ctrlEVP_PKEY_copy_parametersEVP_PKEY2PKCS8_brokenEVP_PKCS82PKEY_BROKENEVP_PKCS82PKEYEVP_PBE_CipherInitEVP_PBE_alg_add_typeEVP_PBE_alg_addEVP_OpenInitEVP_MD_sizeEVP_MD_CTX_copy_exEVP_EncryptFinal_exEVP_DigestInit_exEVP_DecryptFinal_exEVP_CIPHER_CTX_set_key_lengthEVP_CIPHER_CTX_ctrlEVP_CIPHER_CTX_copyEVP_CipherInit_exECKEY_PKEY2PKCS8ECDSA_PKEY2PKCS8DSA_PKEY2PKCS8DSAPKEY2PKCS8DO_SIGVER_INITD2I_PKEYCMAC_INITCAMELLIA_INIT_KEYAES_XTS_CIPHERAES_XTSAES_INIT_KEYAESNI_XTS_CIPHERAESNI_INIT_KEYОcamellia256CAMELLIA256camellia192CAMELLIA192camellia128CAMELLIA128aes256AES256aes192AES192aes128AES128cast-cbcCAST-cbccastCASTblowfishbfBFrc2RC2SEEDideaIDEAdes3DES3desDESdesxDESXrmd160ripemddss1DSS1ssl3-sha1ssl3-md5ssl2-md5.\crypto\evp\evp_lib.cl <= sizeof(c->iv)j <= sizeof(c->iv)reliable.\crypto\evp\bio_ok.cThe quick brown fox jumped over the lazy dog's back.TYPE=.\crypto\evp\evp_pkey.c P PD@PE@ a@ ,@ +@ %@ b@ PP@P@ !*).\crypto\evp\evp_pbe.cEVP_CIPHER_iv_length(cipher) <= 16EVP_CIPHER_key_length(cipher) <= (int)sizeof(md_tmp).\crypto\evp\p5_crpt.ckeylen <= sizeof key.\crypto\evp\p5_crpt2.c.\crypto\evp\pmeth_lib.cdigest.\crypto\evp\pmeth_fn.c.\crypto\evp\pmeth_gn.c.\crypto\evp\m_sigver.c.\crypto\asn1\a_object.c.\crypto\asn1\a_bitstr.cc ;; ;%02d%02d%02d%02d%02d%02dZ.\crypto\asn1\a_utctm.ccc ;; ;%04d%02d%02d%02d%02d%02dZ.\crypto\asn1\a_gentm.cASN1_TIMEL.\crypto\asn1\a_time.c2019.\crypto\asn1\a_int.c.\crypto\asn1\a_set.c.\crypto\asn1\a_dup.c.\crypto\asn1\a_d2i_fp.c.\crypto\asn1\a_i2d_fp.c.\crypto\asn1\a_enum.c.\crypto\asn1\a_sign.c.\crypto\asn1\a_digest.c.\crypto\asn1\a_verify.c'()+,-./:=?maxsize=minsize=%ld.\crypto\asn1\a_mbstr.cx(  0123456789ABCDEF\%02X\U%04lX\W%08lX.\crypto\asn1\a_strex.c#"= = + ; +,, X509_ALGORSalgorithmsX509_ALGORparameter$\ lOxO`OTO3OHOX509_VALnotAfternotBeforePpOpPOX509_PUBKEYpublic_keyalgor5lP3`P PtP TP.\crypto\asn1\x_pubkey.cX509_SIGlP3LKPPX509_REQsignaturesig_algreq_infoX509_REQ_INFOattributespubkeysubject< @  QCQ5xQP>QQhQ \Q =TQ3HQ 4RRS RBIGNUM/HS/HSZLONGLONG0S0S.\crypto\asn1\x_long.c%ld X509_NAMEX509_NAME_INTERNALNameX509_NAME_ENTRIESRDNSX509_NAME_ENTRYvalueRDT@LT4T,T`BTTTCTSC@DI0KFTS.\crypto\asn1\x_name.ccert_infoX509_CINFextensionssubjectUIDissuerUIDvalidityissuer(@  @u  HQ3 UC|U@5QCX 5pU  dU $XUU U4LUL@UKTQ3HQ VVhT~ X509_CERT_PAIRreverseforwardX509_CERT_AUXotherkeyidaliasrejecttrustLWDW %*s %*s%s: %*s%s OF %s { SEQUENCESET.\crypto\asn1\ameth_lib.c\ 00.\crypto\asn1\f_int.c.\crypto\asn1\f_string.cNETSCAPE_PKEYprivate_keyNETSCAPE_ENCRYPTED_PKEYenckeyos`iXip<|idi@i@ @lP34ii $iSGCKEYSALTEnter Private Key password:private-key.\crypto\asn1\n_pkey.c.\crypto\asn1\f_enum.c.\crypto\asn1\x_pkey.c.\crypto\asn1\a_bool.cX509_EXTENSIONSExtensionX509_EXTENSIONR\DTj jj0kjasn1.\crypto\asn1\bio_asn1.cctx->buflen <= ctx->bufsize.\crypto\asn1\bio_ndef.c.\crypto\asn1\asn_mime.cgostr3411-94sha-512sha-384sha-256-- Content-Type: text/plain -----END %s----- -----BEGIN %s----- Content-Transfer-Encoding: base64%s%s name="%s"%s smime-type=%s;Content-Type: %smime; filename="%s"%ssmime.p7zcompressed-datacerts-onlysigned-datasigned-receiptenveloped-data%s------%s--%s%s filename="smime.p7s"%s%sContent-Disposition: attachment;Content-Transfer-Encoding: base64%s name="smime.p7s"%sContent-Type: %ssignature;%s------%s%s------%s%sThis is an S/MIME signed message%s%s"; boundary="----%s"%s%s micalg=" protocol="%ssignature";Content-Type: multipart/signed;MIME-Version: 1.0%sapplication/pkcs7-application/x-pkcs7-smime.p7mapplication/pkcs7-mimeapplication/x-pkcs7-mimetype: application/pkcs7-signatureapplication/x-pkcs7-signatureboundarymultipart/signedcontent-typetext/plainFORMATFORMBITWRAPSETWRAPSEQWRAPOCTWRAPIMPLICITIMPEXPLICITEXPSEQNUMERICSTRINGNUMERICGENSTRGeneralStringTELETEXSTRINGT61STRINGT61PRINTABLEPRINTABLESTRINGVISIBLEVISIBLESTRINGBMPSTRINGBMPUTF8StringUTF8IA5STRINGIA5UNIVUNIVERSALSTRINGBITSTRINGBITSTROCTETSTRINGOCTGENTIMEGENERALIZEDTIMEUTCUTCTIMEOBJECTOIDENUMERATEDENUMINTEGERINTBOOLEANBOOLqq ppp p pppppppp pp |ptpppdp \p Pp Lp@p 0p (pp p po o o ooo hohoooooooxopohoChar=.\crypto\asn1\asn1_gen.cBITLISTHEXASCIItag=string=GENERALSTRINGGRAPHICSTRINGVIDEOTEXSTRINGUTF8STRINGREALEXTERNALOBJECT DESCRIPTOROCTET STRINGBIT STRINGEOC%-18s`tqpTtDt p0t$ttpttssshhoposdppps0ps|ps@p(unknown)appl [ %d ]cont [ %d ]priv [ %d ] prim: cons: length is greater than %ld Error in encoding BAD ENUMERATEDBAD INTEGER[HEX DUMP]::%dBad boolean :BAD OBJECTd=%-2d hl=%ld l=inf d=%-2d hl=%ld l=%4ld %5ld:ASN.1 part of OpenSSL 1.0.1c 10 May 2012.\crypto\asn1\asn1_lib.caddress= offset=%luwrong typewrong tagunsupported typeunsupported public key typeunsupported encryption algorithmunsupported any defined by typeunkown formatunknown tagunknown signature algorithmunknown public key typeunknown object typeunknown message digest algorithmunknown formatuniversalstring is wrong lengthunexpected eocunable to decode rsa private keyunable to decode rsa keytype not constructedtoo longtime not ascii formattag value too highstring too shortstring too longstreaming not supportedsig invalid mime typeshort linesequence or set needs configsequence not constructedsequence length mismatchsecond number too largeprivate key header missingodd number of charsobject not ascii formatnull is wrong lengthno sig content typeno multipart boundaryno multipart body failureno matching choice typeno content typenot enough datanot ascii formatnon hex charactersnested asn1 stringmstring wrong tagmstring not universalmissing valuemissing second numbermissing eocmime sig parse errormime parse errormime no content typelist errorlength errorinvalid utf8stringinvalid universalstring lengthinvalid time formatinvalid separatorinvalid object encodinginvalid numberinvalid modifierinvalid mime typeinvalid digitinvalid bmpstring lengthinteger too large for longinteger not ascii formatillegal time valueillegal tagged anyillegal options on item templateillegal optional anyillegal objectillegal null valueillegal nullillegal nested taggingillegal integerillegal implicit tagillegal hexillegal formatillegal charactersillegal booleanillegal bitstring formatheader too longfirst num too largefield missingexplicit tag not constructedexplicit length mismatchexpecting a timeexpecting a booleanexpecting an objectexpecting an integererror setting cipher paramserror parsing set elementerror loading sectionerror getting timedigest and key type not supporteddepth exceededdecoding errordata is wrongcontext not initialisedcipher has no object identifierboolean is wrong lengthbn libbmpstring is wrong lengthbad tagbad password readbad object headerbad classaux errorasn1 sig parse errorasn1 parse erroradding objectX509_PKEY_newX509_NEWX509_NAME_EX_NEWX509_NAME_EX_D2IX509_NAME_ENCODEX509_INFO_newX509_CRL_add0_revokedX509_CINF_NEWSMIME_textSMIME_read_ASN1PKCS5_pbkdf2_setPKCS5_pbe_set0_algorPKCS5_pbe_setPKCS5_pbe2_set_ivPARSE_TAGGINGOID_MODULE_INITLONG_C2Ii2d_RSA_PUBKEYi2d_RSA_NETi2d_PublicKeyi2d_PrivateKeyi2d_EC_PUBKEYi2d_DSA_PUBKEYI2D_ASN1_TIMEi2d_ASN1_SETi2d_ASN1_bio_streamd2i_X509_PKEYD2I_X509_CINFD2I_X509D2I_RSA_NET_2d2i_RSA_NETd2i_PublicKeyd2i_PrivateKeyD2I_NETSCAPE_RSA_2d2i_Netscape_RSAd2i_AutoPrivateKeyD2I_ASN1_UTCTIMEd2i_ASN1_UINTEGERd2i_ASN1_type_bytesd2i_ASN1_SETd2i_ASN1_OBJECTD2I_ASN1_INTEGERD2I_ASN1_HEADERD2I_ASN1_GENERALIZEDTIMEd2i_ASN1_bytesd2i_ASN1_BOOLEAND2I_ASN1_BIT_STRINGCOLLECT_DATAc2i_ASN1_OBJECTc2i_ASN1_INTEGERc2i_ASN1_BIT_STRINGBN_to_ASN1_INTEGERBN_to_ASN1_ENUMERATEDBITSTR_CBBIO_new_NDEFB64_WRITE_ASN1B64_READ_ASN1ASN1_verifyASN1_UTCTIME_setASN1_UTCTIME_adjASN1_unpack_stringASN1_TYPE_get_octetstringASN1_TYPE_get_int_octetstringASN1_TIME_setASN1_TIME_adjASN1_TEMPLATE_NOEXP_D2IASN1_TEMPLATE_NEWASN1_TEMPLATE_EX_D2IASN1_STRING_type_newASN1_STRING_TABLE_addASN1_STRING_setASN1_STR2TYPEASN1_signASN1_seq_unpackASN1_seq_packASN1_PKCS5_PBE_SETASN1_PCTX_newASN1_pack_stringASN1_OUTPUT_DATAASN1_OBJECT_newASN1_mbstring_ncopyASN1_item_verifyASN1_item_unpackASN1_item_sign_ctxASN1_item_signASN1_item_packASN1_item_i2d_fpASN1_item_i2d_bioASN1_ITEM_EX_D2IASN1_ITEM_EX_COMBINE_NEWASN1_item_dupASN1_item_d2i_fpASN1_INTEGER_to_BNASN1_INTEGER_setASN1_i2d_fpASN1_i2d_bioASN1_HEADER_NEWASN1_get_objectASN1_generate_v3ASN1_GENERALIZEDTIME_setASN1_GENERALIZEDTIME_adjASN1_FIND_ENDASN1_EX_C2IASN1_ENUMERATED_to_BNASN1_ENUMERATED_setASN1_dupASN1_DO_ADBASN1_digestASN1_D2I_READ_BIOASN1_d2i_fpASN1_D2I_EX_PRIMITIVEASN1_COLLECTASN1_COLLATE_PRIMITIVEASN1_CHECK_TLENASN1_CBASN1_BIT_STRING_set_bitAPPEND_EXPa2i_ASN1_STRINGa2i_ASN1_INTEGERa2i_ASN1_ENUMERATEDa2d_ASN1_OBJECT.\crypto\asn1\a_bytes.c @(((@(@(01(6(7(c(d(e(i@(defaultutf8onlypkixnombstrMASK:.\crypto\asn1\a_strnid.c.\crypto\asn1\evp_asn1.c.\crypto\asn1\asn_pack.cPBEPARAMitersaltPH X<.\crypto\asn1\p5_pbe.cPBKDF2PARAMprfkeylengthPBE2PARAMencryptionkeyfunc3܊3ЊPPH Ċ  3.\crypto\asn1\p5_pbev2.cPKCS8_PRIV_KEY_INFOpkeypkeyalg@7@  ؋3 ЋxQP>.\crypto\asn1\asn_moid.coid_section.\crypto\pem\pem_sign.c.\crypto\pem\pem_seal.cEC PRIVATE KEYDSA PRIVATE KEYRSA PRIVATE KEYX509 CRLTRUSTED CERTIFICATEX509 CERTIFICATECERTIFICATE.\crypto\pem\pem_info.cstrlen(objstr)+23+2*enc->iv_len+13 <= sizeof bufPEM part of OpenSSL 1.0.1c 10 May 20120123456789ABCDEF.\crypto\pem\pem_lib.cphrase is too short, needs to be at least %d chars Enter PEM pass phrase:Proc-Type: 4,BAD-TYPEMIC-ONLYMIC-CLEARENCRYPTEDDEK-Info: -----END ----- -----BEGIN CMSPKCS #7 SIGNED DATAPKCS7CERTIFICATE REQUESTNEW CERTIFICATE REQUESTPARAMETERSPRIVATE KEYENCRYPTED PRIVATE KEYANY PRIVATE KEYenc->iv_len <= (int)sizeof(iv)Proc-Type: Expecting: RSA PUBLIC KEYPUBLIC KEYDSA PARAMETERSEC PARAMETERSDH PARAMETERSunsupported key componentsunsupported encryptionshort headerread keypvk too shortpvk data too shortpublic key no rsaproblems getting passwordno start linenot proc typenot encryptednot dek infokeyblob too shortkeyblob header parse errorinconsistent headerexpecting public key blobexpecting private key bloberror converting private keycipher is nullbio write failurebad version numberbad magic numberbad iv charsbad end linebad base64 decodePEM_X509_INFO_write_bioPEM_X509_INFO_read_bioPEM_X509_INFO_readPEM_WRITE_PRIVATEKEYPEM_write_bioPEM_writePEM_SignFinalPEM_SealInitPEM_SealFinalPEM_READ_PRIVATEKEYPEM_READ_BIO_PRIVATEKEYPEM_read_bio_ParametersPEM_read_bioPEM_readPEM_PK8PKEYPEM_get_EVP_CIPHER_INFOPEM_F_PEM_WRITE_PKCS8PRIVATEKEYPEM_do_headerPEM_def_callbackPEM_ASN1_write_bioPEM_ASN1_writePEM_ASN1_read_bioPEM_ASN1_readLOAD_IVi2b_PVK_bioI2B_PVKDO_PVK_HEADERDO_PVK_BODYDO_PK8PKEY_FPDO_PK8PKEYDO_BLOB_HEADERDO_B2I_BIODO_B2Id2i_PKCS8PrivateKey_fpd2i_PKCS8PrivateKey_bioCHECK_BITLEN_RSACHECK_BITLEN_DSAB2I_RSAb2i_PVK_bioB2I_DSSCERTIFICATE PAIR.\crypto\pem\pem_oth.c.\crypto\pem\pem_pk8.c.\crypto\pem\pem_pkey.c%s PRIVATE KEY%s PARAMETERS.\crypto\pem\pvkfmt.c/usr/local/ssl/private/usr/local/ssl/usr/local/ssl/certs/usr/local/ssl/cert.pemSSL_CERT_DIRSSL_CERT_FILE.\crypto\x509\x509_r2x.c.\crypto\x509\x509_cmp.c0123456789ABCDEF.\crypto\x509\x509_obj.cNO X509_NAME.\crypto\x509\x509_req.c.\crypto\x509\x509spki.cX.509 part of OpenSSL 1.0.1c 10 May 2012.\crypto\x509\x509_vfy.cOPENSSL_ALLOW_PROXY_CERTSwrong lookup typeunknown trust idunknown purpose idunknown key typeunable to get certs public keyunable to find parameters in chainshould retrypublic key encode errorpublic key decode errorno cert set for us to verifyloading defaultsloading cert dirkey values mismatchkey type mismatchinvalid trustinvalid field nameinvalid directoryerr asn1 libcert already in hash tablecant check dh keybase64 decode errorbad x509 filetypeX509_verify_certX509_TRUST_setX509_TRUST_addX509_to_X509_REQX509_STORE_CTX_purpose_inheritX509_STORE_CTX_newX509_STORE_CTX_initX509_STORE_CTX_get1_issuerX509_STORE_add_crlX509_STORE_add_certX509_REQ_to_X509X509_REQ_print_fpX509_REQ_print_exX509_REQ_check_private_keyX509_PUBKEY_setX509_PUBKEY_getX509_print_ex_fpX509_NAME_printX509_NAME_onelineX509_NAME_ENTRY_set_objectX509_NAME_ENTRY_create_by_txtX509_NAME_ENTRY_create_by_NIDX509_NAME_add_entryX509_load_crl_fileX509_load_cert_fileX509_load_cert_crl_fileX509_get_pubkey_parametersX509_EXTENSION_create_by_OBJX509_EXTENSION_create_by_NIDX509_CRL_print_fpX509_check_private_keyX509_ATTRIBUTE_set1_dataX509_ATTRIBUTE_get0_dataX509_ATTRIBUTE_create_by_txtX509_ATTRIBUTE_create_by_OBJX509_ATTRIBUTE_create_by_NIDX509v3_add_extX509at_add1_attrNETSCAPE_SPKI_b64_encodeNETSCAPE_SPKI_b64_decodeGET_CERT_BY_SUBJECTDIR_CTRLCHECK_POLICYBY_FILE_CTRLADD_CERT_DIR.\crypto\x509\x509name.cname=.\crypto\x509\x509_v3.c.\crypto\x509\x509_att.c.\crypto\x509\x509_lu.cerror number %ldCRL path validation errorunsupported or invalid name syntaxunsupported or invalid name constraint syntaxunsupported name constraint typename constraints minimum and maximum not supportedexcluded subtree violationpermitted subtree violationRFC 3779 resource not subset of parent's resourcesUnsupported extension featureDifferent CRL scopeno explicit policyinvalid or inconsistent certificate policy extensioninvalid or inconsistent certificate extensionunhandled critical CRL extensionkey usage does not include digital signaturekey usage does not include CRL signingunhandled critical extensionunable to get CRL issuer certificatekey usage does not include certificate signingauthority and issuer serial number mismatchauthority and subject key identifier mismatchsubject issuer mismatchapplication verification failurecertificate rejectedcertificate not trustedunsupported certificate purposeproxy certificates not allowed, please set the appropriate flagproxy path length constraint exceededpath length constraint exceededinvalid non-CA certificate (has CA markings)invalid CA certificatecertificate revokedcertificate chain too longunable to verify the first certificateunable to get local issuer certificateself signed certificate in certificate chainself signed certificateout of memoryformat error in CRL's nextUpdate fieldformat error in CRL's lastUpdate fieldformat error in certificate's notAfter fieldformat error in certificate's notBefore fieldCRL has expiredcertificate has expiredCRL is not yet validcertificate is not yet validCRL signature failurecertificate signature failureunable to decode issuer public keyunable to decrypt CRL's signatureunable to decrypt certificate's signatureunable to get certificate CRLunable to get issuer certificateokTSA serverOCSP requestOCSP responderObject SignerS/MIME emailSSL ServerSSL Clientcompatible.\crypto\x509\x509_trs.cLoad file into cache.\crypto\x509\by_file.cLoad certs from files in a directory.\crypto\x509\by_dir.c%s%c%08lx.%s%dssl_serverssl_clientsmime_signd} PD8.\crypto\x509\x509_vpm.cBASIC_CONSTRAINTSpathlencaWp! ! 0" 80 tCAsection:,name:,value:.\crypto\x509v3\v3_bcons.cdecipherOnlyDecipher OnlyencipherOnlyEncipher OnlycRLSignCRL SignkeyCertSignCertificate SignkeyAgreementKey AgreementdataEnciphermentData EnciphermentkeyEnciphermentKey EnciphermentnonRepudiationNon RepudiationdigitalSignatureDigital SignatureobjCAObject Signing CAemailCAS/MIME CAsslCASSL CAreservedUnusedobjsignObject SigningemailserverclientG # # (>S # # >.\crypto\x509v3\v3_bitst.c.\crypto\x509v3\v3_conf.ccritical,ASN1:DER:,section=value=, value=EXTENDED_KEY_USAGE~@0 0 @1 p@0 0 @1 .\crypto\x509v3\v3_extku.cH02 2 I02 2 J02 2 K02 2 L02 2 M02 2 N02 2 .\crypto\x509v3\v3_ia5.c.\crypto\x509v3\v3_lib.c %*s%*s%*s%s0123456789ABCDEF.\crypto\x509v3\v3_utl.cnoNONfalseyesYESyYtrueuser too longunsupported optionunknown optionunknown extension nameunknown extensionunknown bit string argumentunable to get issuer keyidunable to get issuer detailssection not foundpolicy when proxy language requires no policypolicy syntax not currently supportedpolicy path length already definedpolicy path lengthpolicy language already definedothername erroroperation not definedodd number of digitsno subject detailsno public keyno proxy cert policy language definedno policy identifierno issuer detailsno issuer certificateno config databaseneed organization and numbersissuer decode errorinvalid syntaxinvalid sectioninvalid safiinvalid purposeinvalid proxy policy settinginvalid policy identifierinvalid optioninvalid object identifierinvalid numbersinvalid null valueinvalid null nameinvalid null argumentinvalid nameinvalid ipaddressinvalid inheritanceinvalid extension stringinvalid boolean stringinvalid asrangeinvalid asnumberinvalid multiple rdnsincorrect policy syntax tagillegal hex digitillegal empty extensionextension value errorextension setting not supportedextension not foundextension name errorextension existsexpected a section nameerror in extensionerror creating extensionerror converting zoneduplicate zone iddistpoint already setdirname errorbn to asn1 integer errorbn dec2bn errorbad objectbad ip addressX509_PURPOSE_setX509_PURPOSE_addX509V3_parse_listX509V3_get_value_boolX509V3_get_stringX509V3_get_sectionX509V3_EXT_nconfX509V3_EXT_i2dX509V3_EXT_confX509V3_EXT_add_aliasX509V3_EXT_addX509V3_add_valueX509V3_add1_i2dV3_GENERIC_EXTENSIONV3_ADDR_VALIDATE_PATH_INTERNALV2I_SUBJECT_ALTV2I_POLICY_MAPPINGSV2I_POLICY_CONSTRAINTSV2I_NAME_CONSTRAINTSV2I_ISSUER_ALTV2I_IPADDRBLOCKSV2I_IDPv2i_GENERAL_NAME_exv2i_GENERAL_NAMESV2I_EXTENDED_KEY_USAGEV2I_CRLDV2I_BASIC_CONSTRAINTSV2I_AUTHORITY_KEYIDV2I_AUTHORITY_INFO_ACCESSv2i_ASN1_BIT_STRINGV2I_ASIDENTIFIERSSXNET_get_id_ulongSXNET_get_id_ascSXNET_add_id_ulongSXNET_add_id_INTEGERSXNET_add_id_ascstring_to_hexSET_DIST_POINT_NAMES2I_SKEY_IDS2I_ASN1_SKEY_IDs2i_ASN1_OCTET_STRINGs2i_ASN1_INTEGERS2I_ASN1_IA5STRINGR2I_PCIR2I_CERTPOLPROCESS_PCI_VALUEPOLICY_SECTIONNREF_NOSNOTICE_SECTIONI2V_AUTHORITY_INFO_ACCESSi2s_ASN1_INTEGERI2S_ASN1_IA5STRINGi2s_ASN1_ENUMERATEDhex_to_stringGNAMES_FROM_SECTNAMEDO_I2V_NAME_CONSTRAINTSDO_EXT_NCONFDO_EXT_I2DDO_EXT_CONFDO_DIRNAMECOPY_ISSUERCOPY_EMAILASIDENTIFIERCHOICE_IS_CANONICALASIDENTIFIERCHOICE_CANONIZEA2I_GENERAL_NAMEGENERAL_NAMESGeneralNamesGENERAL_NAMEd.registeredIDd.iPAddressd.uniformResourceIdentifierd.ediPartyNamed.directoryNamed.x400Addressd.dNSNamed.rfc822Named.otherNameEDIPARTYNAMEpartyNamenameAssignerOTHERNAMEtype_idDT@t@dXP H0<0,C pQ 0Է0 ķQ UpR 0] b VpR 0] ` pR 0] Registered IDIP Address%XDirNameURIDNSEdiPartyNameX400NameothernameIP Address::%XIP Address:%d.%d.%d.%dDirName: URI:%sDNS:%semail:%sEdiPartyName:X400Name:othername:.\crypto\x509v3\v3_alt.csection=otherNamedirNameIPRIDcopymoveRd d .\crypto\x509v3\v3_skey.chashZ@  f f serial.\crypto\x509v3\v3_akey.calwaysPKEY_USAGE_PERIODTi Pj POTNot After: Not Before: X >  >  > j AACompromiseAA CompromiseprivilegeWithdrawnPrivilege WithdrawnremoveFromCRLRemove From CRLcertificateHoldCertificate HoldcessationOfOperationCessation Of OperationsupersededSupersededaffiliationChangedAffiliation ChangedCACompromiseCA CompromisekeyCompromiseKey CompromiseunspecifiedUnspecifiedj DSXNETidsSXNETIDuserzonek Pp @l  D@  @k  %*sZone: %s, User: %*sVersion: %ld (0x%lX).\crypto\x509v3\v3_sxnet.cNOTICEREFnoticenosorganizationUSERNOTICEexptextnoticerefPOLICYQUALINFOpqualidd.usernoticed.cpsurid.otherPOLICYINFOqualifierspolicyidCERTIFICATEPOLICIESYp { `| pq  r <0xr p`q `Ts L$@0$ h.\crypto\x509v3\v3_cpols.c%*sExplicit Text: %s %*sNumber%s: %*sOrganization: %s noticeNumbersexplicitText%*sCPS: %s %*sUser Notice: %*sUnknown Qualifier: %*sNo Qualifiers %*s%s Non CriticalCritical%*sPolicy: userNoticeCPSpolicyIdentifieria5orgISSUING_DIST_POINTonlyattrindirectCRLonlysomereasonsonlyCAonlyuserCRL_DIST_POINTSCRLDistributionPointsDIST_POINTCRLissuerreasonsdistpointDIST_POINT_NAMEname.relativenamename.fullnameunusedgp  @ Yp  @ hxhXD0$Ծľ|l\0 Q `B thp ` TQ H0 L hp      ` .\crypto\x509v3\v3_crld.c%*s%s: %*s%*sRelative Name: %*s%*sFull Name: %*sOnly Attribute Certificates Only Some Reasons%*sIndirect CRL %*sOnly CA Certificates %*sOnly User Certificates %*sCRL Issuer: ReasonsrelativenamefullnameonlyAAtimestampsignTime Stamp signingocsphelperOCSP helperanyAny PurposecrlsignCRL signingsmimeencryptS/MIME encryptionsmimesignS/MIME signingnssslserverNetscape SSL serversslserverSSL serversslclientSSL clientGSUWY~.\crypto\x509v3\v3_purp.cAUTHORITY_INFO_ACCESSACCESS_DESCRIPTIONlocationmethod 0   0  Q <0  - .\crypto\x509v3\v3_info.co`  r   n0   @  q P s ` %*scrlTime: %*scrlNum: %*scrlUrl: .\crypto\x509v3\v3_ocsp.c %*s%*sIssuer: AUTHORITY_KEYID4WUQ ܼ  POLICY_MAPPINGSPOLICY_MAPPINGsubjectDomainPolicyissuerDomainPolicyХ   L8( .\crypto\x509v3\v3_pmaps.cPOLICY_CONSTRAINTSinhibitPolicyMappingrequireExplicitPolicy`   T < (Inhibit Policy MappingRequire Explicit Policy.\crypto\x509v3\v3_pcons.cNAME_CONSTRAINTSexcludedSubtreespermittedSubtreesGENERAL_SUBTREEmaximumminimum    Q    p\p Hp  4.\crypto\x509v3\v3_ncons.cexcludedpermitted%d.%d.%d.%d/%d.%d.%d.%dIP:ExcludedPermittedPROXY_CERT_INFO_EXTENSIONproxyPolicypcPathLengthConstraintPROXY_POLICYpolicypolicyLanguage$4   x   %*sPolicy Text: %s %*sPolicy Language: infinite%*sPath Length Constraint: text:file:hex:.\crypto\x509v3\v3_pci.clanguage.\crypto\x509v3\pcy_cache.c.\crypto\x509v3\pcy_node.c.\crypto\x509v3\pcy_data.c.\crypto\x509v3\pcy_tree.c.\crypto\cms\cms_lib.cCMS_ReceiptoriginatorSignatureValueCMS_ReceiptRequestreceiptsToreceiptsFromsignedContentIdentifierCMS_ReceiptsFromd.receiptListd.allOrFirstTierCMS_Attributes_VerifyCMS_Attributes_SignCMS_ATTRIBUTESCMS_ContentInfod.compressedDatad.authenticatedDatad.encryptedDatad.digestedDatad.envelopedDatad.signedDatad.dataCMS_CompressedDatacompressionAlgorithmCMS_AuthenticatedDataunauthAttrsmacauthAttrsmacAlgorithmCMS_EncryptedDataCMS_DigestedDataCMS_EnvelopedDataunprotectedAttrsencryptedContentInforecipientInfosoriginatorInfoCMS_RecipientInfod.orid.pwrid.kekrid.karid.ktriCMS_OtherRecipientInfooriValueoriTypeCMS_PasswordRecipientInfokeyDerivationAlgorithmCMS_KEKRecipientInfokekidCMS_KEKIdentifierkeyIdentifierCMS_KeyAgreeRecipientInforecipientEncryptedKeysukmoriginatorCMS_OriginatorIdentifierOrKeyd.originatorKeyCMS_OriginatorPublicKeyCMS_RecipientEncryptedKeyCMS_KeyAgreeRecipientIdentifierd.rKeyIdCMS_RecipientKeyIdentifierdateCMS_OtherKeyAttributekeyAttrkeyAttrIdCMS_KeyTransRecipientInfoencryptedKeykeyEncryptionAlgorithmridCMS_EncryptedContentInfoencryptedContentcontentEncryptionAlgorithmCMS_OriginatorInfoCMS_SignedDatasignerInfoscrlscertificatesencapContentInfodigestAlgorithmsCMS_RevocationInfoChoiced.crlCMS_OtherRevocationInfoFormatotherRevInfootherRevInfoFormatCMS_SignerInfounsignedAttrssignatureAlgorithmsignedAttrsdigestAlgorithmsidCMS_EncapsulatedContentInfoeContenteContentTypeCMS_SignerIdentifierd.subjectKeyIdentifierd.issuerAndSerialNumberCMS_CertificateChoicesd.v2AttrCertd.v1AttrCertd.extendedCertificated.certificateCMS_OtherCertificateFormatotherCertotherCertFormatCMS_IssuerAndSerialNumberUC@u  hH8,L  phXL 0 @ @, 3 P>3HQP>$`TP t@ @`3L  < 4` (@ @< 4` { 3@ @ 3 ppd\Dw <,W     x $\ 3<    DL@ @  3h <<,W  (@ @  3 @ @33 L`   0 @ P l@ @\ L  4  P>( @ @3L  LK@ @4  P>  $@ @\ L  33L 3 3@ @3 L <tl\p L < ,   @ { 0 lP> P>@pR (hX LpR l 8@ @{ h .\crypto\cms\cms_io.c.\crypto\cms\cms_smime.cVerify error:wrap errorverification failureunwrap failureunwrap errorunsupported recpientinfo typeunsupported recipient typeunsupported key encryption algorithmunsupported kek algorithmunsupported content typeunsupported compression algorithmunknown idunknown digest algorihmunable to finalize contexttype not enveloped datatype not encrypted datatype not digested datatype not datatype not compressed datastore init errorsmime text errorsignfinal errorsigner certificate not foundrecipient errorreceipt decode errorprivate key does not match certificateno signersno receipt requestno private keyno passwordno msgsigdigestno matching signatureno matching recipientno matching digestno key or certno keyno contentno ciphernot supported for this key typenot pwrinot key transportnot keknot encrypted datanot a signed receiptneed one signermsgsigdigest wrong lengthmsgsigdigest verification failuremsgsigdigest errormessagedigest wrong lengthmessagedigest attribute wrong lengthmd bio init errorinvalid key encryption parameterinvalid encrypted key lengtherror setting recipientinfoerror setting keyerror reading messagedigest attributeerror getting public keydigest errordecrypt errorctrl failurectrl errorcontent verify errorcontent type not signed datacontent type not enveloped datacontent type not compressed datacontent type mismatchcontent not foundcontentidentifier mismatchcms libcms datafinal errorcipher parameter initialisation errorcipher initialisation errorcertificate verify errorcertificate has no keyidcertificate already presentadd signer errorCMS_verifyCMS_uncompressCMS_streamCMS_sign_receiptCMS_SignerInfo_verify_contentCMS_SIGNERINFO_VERIFY_CERTCMS_SignerInfo_verifyCMS_SignerInfo_signCMS_SIGNERINFO_CONTENT_SIGNCMS_SIGNED_DATA_INITCMS_signCMS_set_detachedcms_set1_SignerIdentifierCMS_RecipientInfo_set0_pkeyCMS_RecipientInfo_set0_passwordCMS_RecipientInfo_set0_keycms_RecipientInfo_pwri_cryptCMS_RecipientInfo_ktri_get0_signer_idCMS_RecipientInfo_ktri_get0_algsCMS_RECIPIENTINFO_KTRI_ENCRYPTCMS_RECIPIENTINFO_KTRI_DECRYPTCMS_RecipientInfo_ktri_cert_cmpCMS_RecipientInfo_kekri_id_cmpCMS_RecipientInfo_kekri_get0_idCMS_RECIPIENTINFO_KEKRI_ENCRYPTCMS_RECIPIENTINFO_KEKRI_DECRYPTCMS_RecipientInfo_decryptcms_Receipt_verifyCMS_ReceiptRequest_create0cms_msgSigDigest_add1CMS_GET0_SIGNEDCMS_GET0_REVOCATION_CHOICEScms_get0_envelopedCMS_GET0_ECONTENT_TYPECMS_get0_contentCMS_GET0_CERTIFICATE_CHOICESCMS_finalCMS_ENVELOPED_DATA_INITcms_EnvelopedData_init_bioCMS_EnvelopedData_createCMS_EncryptedData_set1_keyCMS_EncryptedData_encryptCMS_EncryptedData_decryptcms_EncryptedContent_init_bioCMS_encryptcms_encode_ReceiptCMS_digest_verifycms_DigestedData_do_finalcms_DigestAlgorithm_init_biocms_DigestAlgorithm_find_ctxCMS_decrypt_set1_pkeyCMS_decrypt_set1_passwordCMS_decrypt_set1_keyCMS_decryptCMS_dataInitCMS_dataFinalCMS_dataCMS_COPY_MESSAGEDIGESTCMS_COPY_CONTENTcms_CompressedData_init_biocms_CompressedData_createCMS_compressCMS_ADD1_SIGNINGTIMECMS_add1_signerCMS_add1_recipient_certCMS_add1_ReceiptRequestCMS_add0_recipient_passwordCMS_add0_recipient_keyCMS_add0_certCHECK_CONTENT.\crypto\cms\cms_sd.c.\crypto\cms\cms_dd.c.\crypto\cms\cms_env.c.\crypto\cms\cms_enc.c.\crypto\cms\cms_ess.c.\crypto\cms\cms_pwri.cvariable has no valueunknown module nameunable to create new sectionno valueno sectionno conf or environment variableno confno close bracemodule initialization errormissing init functionmissing finish functionmissing equal signmissing close square bracketlist cannot be nullerror loading dsoSTR_COPYNCONF_newNCONF_load_fpNCONF_load_bioNCONF_loadNCONF_get_stringNCONF_get_sectionNCONF_get_number_eNCONF_get_numberNCONF_dump_fpNCONF_dump_bioMODULE_RUNMODULE_LOAD_DSOMODULE_INITDEF_LOAD_BIODEF_LOADCONF_parse_listCONF_modules_loadCONF_load_fpCONF_load_bioCONF_loadCONF_dump_fpCONF part of OpenSSL 1.0.1c 10 May 2012.\crypto\conf\conf_lib.cgroup= name=ENVvv == NULL.\crypto\conf\conf_api.cWIN32OpenSSL defaultCONF_def part of OpenSSL 1.0.1c 10 May 2012.\crypto\conf\conf_def.c[[%s]] [%s] %s=%s line .\crypto\conf\conf_mod.copenssl.cnfOPENSSL_CONFmodule=, path=OPENSSL_finishOPENSSL_init, retcode=%-8dopenssl_confAuto configuration failed TXT_DB part of OpenSSL 1.0.1c 10 May 2012OPENSSL_malloc failure wrong number of fields on line %ld (looking for field %d, got %d, '%s' left) failure in sk_push .\crypto\txt_db\txt_db.cPKCS7_ATTR_VERIFYPKCS7_ATTR_SIGNPKCS7_ATTRIBUTESPKCS7_DIGESTmdPKCS7_ENCRYPTPKCS7_SIGN_ENVELOPEPKCS7_ENC_CONTENTcontent_typePKCS7_RECIP_INFOenc_keykey_enc_algorPKCS7_ENVELOPEenc_datarecipientinfoPKCS7_ISSUER_AND_SERIALPKCS7_SIGNER_INFOunauth_attrenc_digestdigest_enc_algauth_attrdigest_algissuer_and_serialPKCS7_SIGNEDsigner_infocontentsmd_algsd.encryptedd.digestd.signed_and_envelopedd.envelopedd.signhl`a T c <d 0e $@e @` P 0` @(@  3` [L (X`T b b @  b 3 P>3P>0 UCܼ t@  dc X@d  Hc t@  b 83 0 $\ 3X@  dc 3X@d [L (X`T b P@  X@d X@  3`  LKP> P>.\crypto\pkcs7\pk7_lib.cwrong pkcs7 typewrong content typeunsupported cipher typeunknown operationunknown digest typeunable to find message digestunable to find mem biounable to find certificatesigning not supported for this key typesigning ctrl failuresignature failurepkcs7 sig parse errorpkcs7 parse errorpkcs7 datasignpkcs7 datafinal errorpkcs7 datafinalpkcs7 add signer errorpkcs7 add signature erroroperation not supported on this typeno signatures on datano recipient matches keyno recipient matches certificateno matching digest type foundmissing ceripend infoinvalid null pointererror setting ciphererror adding recipientencryption not supported for this key typeencryption ctrl failuredigest failuredecrypted key is wrong lengthcontent and data presentcipher not initializedSMIME_read_PKCS7PKCS7_verifyPKCS7_simple_smimecapPKCS7_sign_add_signerPKCS7_SIGNER_INFO_signPKCS7_SIGNER_INFO_setPKCS7_signatureVerifyPKCS7_signPKCS7_set_typePKCS7_set_digestPKCS7_set_contentPKCS7_set_cipherPKCS7_RECIP_INFO_setPKCS7_get0_signersPKCS7_FIND_DIGESTPKCS7_finalPKCS7_encryptPKCS7_ENCODE_RINFOPKCS7_DECRYPT_RINFOPKCS7_decryptPKCS7_dataVerifyPKCS7_DATASIGNPKCS7_dataInitPKCS7_dataFinalPKCS7_dataDecodePKCS7_ctrlPKCS7_COPY_EXISTING_DIGESTPKCS7_BIO_ADD_DIGESTPKCS7_add_signerPKCS7_add_signaturePKCS7_add_recipient_infoPKCS7_add_crlPKCS7_add_certificatePKCS7_add_attrib_smimecapPKCS7_add0_attrib_signing_timei2d_PKCS7_bio_streamDO_PKCS7_SIGNED_ATTRIBB64_WRITE_PKCS7B64_READ_PKCS7.\crypto\pkcs7\pk7_doit.c.\crypto\pkcs7\pk7_smime.c.\crypto\pkcs7\pk7_attr.c.\crypto\pkcs12\p12_add.cPKCS12_AUTHSAFESPKCS12_SAFEBAGSattribPKCS12_SAFEBAGvalue.bagvalue.safesvalue.shkeybagvalue.keybagPKCS12_BAGSvalue.sdsicertvalue.x509crlvalue.x509certvalue.otherPKCS12_MAC_DATAdinfoPKCS12authsafes@   `     p<PH @       | 0P p   p  ` p7P p<D  8  8  8  h T P (   P> (   l  `  .\crypto\pkcs12\p12_crpt.c.\crypto\pkcs12\p12_crt.c.\crypto\pkcs12\p12_decr.c.\crypto\pkcs12\p12_init.c.\crypto\pkcs12\p12_key.c.\crypto\pkcs12\p12_kiss.c.\crypto\pkcs12\p12_mutl.c.\crypto\pkcs12\p12_utl.c.\crypto\pkcs12\p12_npas.cunsupported pkcs12 modeunknown digest algorithmpkcs12 pbe crypt errorpkcs12 cipherfinal errorpkcs12 algor cipherinit errorparse errormac verify failuremac verify errormac string set errormac setup errormac generation errormac absentkey gen erroriv gen errorinvalid null pkcs12 pointererror setting encrypted data typeencrypt errorcontent type not datacant pack structurePKCS8_encryptPKCS8_add_keyusagePKCS12_verify_macPKCS12_unpack_p7dataPKCS12_unpack_authsafesPKCS12_set_macPKCS12_setup_macPKCS12_PBE_keyivgenPKCS12_pbe_cryptPKCS12_parsePKCS12_pack_p7encdataPKCS12_pack_p7dataPKCS12_newpassPKCS12_MAKE_SHKEYBAGPKCS12_MAKE_KEYBAGPKCS12_key_gen_uniPKCS12_key_gen_ascPKCS12_item_pack_safebagPKCS12_item_i2d_encryptPKCS12_item_decrypt_d2iPKCS12_initPKCS12_gen_macPKCS12_createPKCS12_add_localkeyidPKCS12_add_friendlyname_uniPKCS12_add_friendlyname_ascPKCS12_ADD_FRIENDLYNAMEPARSE_BAGSPARSE_BAG.\crypto\pkcs12\p12_p8e.c.\crypto\comp\comp_lib.czlib not supportedzlib inflate errorzlib deflate errorBIO_ZLIB_WRITEBIO_ZLIB_READBIO_ZLIB_NEWBIO_ZLIB_FLUSH(undef)version incompatibilityunimplemented public key methodunimplemented digestunimplemented cipherrsa not implementedprovide parametersno unload functionno such engineno referenceno load functionno indexno control functionnot loadednot initialisedinvalid stringinvalid init valueinvalid cmd numberinvalid cmd nameinternal list errorinit failed'id' or 'name' missingcould not obtain hardware handlefinish failedfailed loading public keyfailed loading private keyengine section errorengine is not in the listengine configuration errorengines section errordso not foundDSO failuredsa not implementeddh not implementedctrl command not implementedconflicting engine idcommand takes no inputcommand takes inputcmd not executableargument is not a numberalready loadedLOG_MESSAGEINT_ENGINE_MODULE_INITINT_ENGINE_CONFIGUREINT_CTRL_HELPERENGINE_up_refENGINE_UNLOCKED_FINISHENGINE_UNLOAD_KEYENGINE_TABLE_REGISTERENGINE_set_nameENGINE_set_idENGINE_SET_DEFAULT_TYPEENGINE_set_default_stringENGINE_removeENGINE_newENGINE_load_ssl_client_certENGINE_load_public_keyENGINE_load_private_keyENGINE_LIST_REMOVEENGINE_LIST_ADDENGINE_initENGINE_get_prevENGINE_get_pkey_methENGINE_get_pkey_asn1_methENGINE_get_nextENGINE_get_digestENGINE_GET_DEFAULT_TYPEENGINE_get_cipherENGINE_FREE_UTILENGINE_finishENGINE_ctrl_cmd_stringENGINE_ctrl_cmdENGINE_ctrlENGINE_cmd_is_executableENGINE_by_idENGINE_addDYNAMIC_SET_DATA_CTXDYNAMIC_LOADDYNAMIC_GET_DATA_CTXDYNAMIC_CTRL.\crypto\engine\eng_lib.c.\crypto\engine\eng_list.cid=LOADDIR_ADDDIR_LOADID/usr/local/ssl/lib/enginesOPENSSL_ENGINES.\crypto\engine\eng_init.c.\crypto\engine\eng_ctrl.c.\crypto\engine\eng_table.c.\crypto\engine\eng_pkey.cPKEY_ASN1PKEY_CRYPTOPKEYDIGESTSCIPHERSRANDECDSAECDHALLstr=.\crypto\engine\eng_fat.c.\crypto\engine\tb_cipher.c.\crypto\engine\tb_digest.c.\crypto\engine\tb_pkmeth.c.\crypto\engine\tb_asnmth.cSoftware engine supportopenssl  a  @Ayy `@d(TEST_ENG_OPENSSL_RC4) test_init_key() called (TEST_ENG_OPENSSL_PKEY)Loading Private key %s default_algorithms, name=initEMPTYLIST_ADDSO_PATHdynamic_pathsoft_loadengine_id.\crypto\engine\eng_cnf.cenginesLoad up the ENGINE specified by other settingsAdds a directory from which ENGINEs can be loadedSpecifies whether to load from 'DIR_ADD' directories (0=no,1=yes,2=mandatory)Whether to add a loaded ENGINE to the internal list (0=no,1=yes,2=mandatory)Specifies an ENGINE id name for loadingSpecifies to continue even if version checking fails (boolean)NO_VCHECKSpecifies the path to the new ENGINE shared libraryDynamic engine loading support,  8 bind_enginev_check.\crypto\engine\eng_dyn.cIntel RDRAND enginerdrandOCSP_SERVICELOClocatorOCSP_CRLIDcrlTimecrlNumcrlUrlOCSP_BASICRESPtbsResponseDataOCSP_RESPDATAresponseExtensionsresponsesproducedAtresponderIdOCSP_SINGLERESPsingleExtensionsthisUpdatecertStatuscertIdOCSP_CERTSTATUSvalue.unknownvalue.revokedvalue.goodOCSP_REVOKEDINFOrevocationReasonrevocationTimeOCSP_RESPIDvalue.byKeyvalue.byNameOCSP_RESPONSEresponseBytesresponseStatusOCSP_RESPBYTESresponseresponseTypeOCSP_REQUESToptionalSignaturetbsRequestOCSP_REQINFOrequestExtensionsrequestListrequestorNameOCSP_ONEREQsingleRequestExtensionsreqCertOCSP_CERTIDissuerKeyHashissuerNameHashOCSP_SIGNATURE3HQ ,[L# # 3## @u  @$##` #$|#@  l#Q `#  L#$<#0#` # \% #""%"""` %""C"(&"x"d"l&P"D" 4" $" &" "` "` ! DX!'!@  !` ! ! !'!x!` 3HQ  ,[L(h!`!0X! P!t( D!UC>>|( -gggxsS՗'''%NAAA2Xs, QS}}}ϔn7IG؎V0p#q|||ǑfffqSݦ{\K.GGGFEB!ʼn---uZXƿyc.8?#GZZuZ/6l333fccc?\ 98Iqqqύd}2II9Irp;Cن_1KHۨ[[q[*4 R)>&&&-L 222dJ}Yj<x3ws榷3:t¾|a'&އ444hHH=Hzu2$Tzzz􍐐z=d__a_> @=hhhghr4ʮ,A^u}TTMTΓv;""" D/dddc*sssHZ$@@@:]z @(H+V蛕3{KۖMa_===zȗf3[6ԃ+++EVnvvvႂ2d(lw6õ[wt)CjjjwPP]P EE ELW8000`+t???~UUIUǢyYeeeejҺhi///e^J'N睎_޾`pl8.FMM)MRdr9vuuu0 6$ @yKcYх8p6~|c>bbb7Uw:)2Mb1R:b3f%%%5JYYyY *Trrr999rLL-LZa^^e^;xxx888p匌 cƲA WCM١aaa/NE{B!!!B4J%xfсDU" NN%NJkQsf `<<|j5@ ޹goL_&,,,}XQkָk\ӌnnnW97n VVEVDD DI^ߞ!7O***MTgֻmk #F⟇SSQSWܮr , X'SN'lllG+111bttt FFF CL &E<PD([BߺXN,:::tiiio $ H-Appp׶Tqogη;~.ۅBBB*WhZ-,IU(((]Pu\\m\1?k"D#臸O6yoR` {5.KWw7JX) k]>g'A}|fG-Z3unsupported versionunsupported md algorithmunacceptable policyts datasigntst info setup errortsa untrustedtsa name mismatchtoken presenttoken not presenttime syscall errorthere must be one signerresponse setup errorpolicy mismatchpkcs7 to ts tst info failedpkcs7 add signed attr errorno time stamp tokennonce not returnednonce mismatchmessage imprint mismatchinvalid signer certificate purposeess signing certificate erroress add signing cert errordetached contentd2i ts resp int failedcould not set timecould not set enginebad typebad pkcs7 typeTS_VERIFY_CTX_newTS_VERIFY_CERTTS_VERIFYTS_TST_INFO_set_tsaTS_TST_INFO_set_timeTS_TST_INFO_set_serialTS_TST_INFO_set_policy_idTS_TST_INFO_set_nonceTS_TST_INFO_set_msg_imprintTS_TST_INFO_set_accuracyTS_RESP_verify_tokenTS_RESP_verify_signatureTS_RESP_SIGNTS_RESP_set_tst_infoTS_RESP_set_status_infoTS_RESP_SET_GENTIME_WITH_PRECISIONTS_RESP_GET_POLICYTS_RESP_CTX_set_status_infoTS_RESP_CTX_set_signer_certTS_RESP_CTX_set_def_policyTS_RESP_CTX_set_certsTS_RESP_CTX_set_accuracyTS_RESP_CTX_newTS_RESP_CTX_add_policyTS_RESP_CTX_add_mdTS_RESP_CTX_add_failure_infoTS_RESP_CREATE_TST_INFOTS_RESP_create_responseTS_REQ_set_policy_idTS_REQ_set_nonceTS_REQ_set_msg_imprintTS_MSG_IMPRINT_set_algoTS_GET_STATUS_TEXTTS_CONF_set_default_engineTS_COMPUTE_IMPRINTTS_CHECK_STATUS_INFOTS_CHECK_SIGNING_CERTSTS_CHECK_POLICYTS_CHECK_NONCESTS_CHECK_IMPRINTSTS_ACCURACY_set_secondsTS_ACCURACY_set_millisTS_ACCURACY_set_microsPKCS7_to_TS_TST_INFOINT_TS_RESP_VERIFY_TOKENESS_SIGNING_CERT_NEW_INITESS_CERT_ID_NEW_INITESS_ADD_SIGNING_CERTDEF_TIME_CBDEF_SERIAL_CBd2i_TS_RESP.\crypto\ts\ts_req_utils.cCertificate required: %s Nonce: unspecified Policy OID: Version: %d .\crypto\ts\ts_rsp_utils.cthe request cannot be handled due to system failurethe additional information requested could not be understood or is not availablethe requested extension is not supported by the TSAthe requested TSA policy is not supported by the TSAthe TSA's time source is not availablethe data submitted has the wrong formattransaction not permitted or supportedunrecognized or unsupported algorithm identifierRevoked.Revocation warning.Waiting.Rejected.Granted with modifications.Granted. micros millis, seconds, Failure info: Status description: out of bounds Status: TSA: Ordering: %s Accuracy: Time stamp: Serial number: Not included. TST info: Status info: .\crypto\ts\ts_rsp_sign.cBad message digest.Message digest algorithm is not supported.Superfluous message digest parameter.Bad request version.Requested policy is not supported..%ld%04d%02d%02d%02d%02d%02dError during serial number generation.Time is not available.Unsupported extension.Error during TSTInfo generation.Error during signature generation.Error during response generation.Bad request format or system error.systemFailureaddInfoNotAvailableunacceptedExtensionunacceptedPolicytimeNotAvailablebadDataFormatbadRequestbadAlgrevocationNotificationrevocationWarningwaitingrejectiongrantedWithModsgranted.\crypto\ts\ts_rsp_verify.cstatus code: , status text: , failure codes: unknown code.\crypto\ts\ts_verify_ctx.cctx != NULLreq != NULL%4sExtensions: Hash Algorithm: %s Message data: unable to load certificate: %s unable to load certificates: %s unable to load private key: %s variable lookup failed for %s::%s invalid variable value for %s::%s tsadefault_tsaengine:.\crypto\ts\ts_conf.cchilbuiltinsigner_certsigner_keydefault_policyother_policiesdigestsmicrosecsmillisecssecsaccuracyclock_precision_digitsorderingtsa_nameess_cert_id_chaincrypto_deviceESS_SIGNING_CERTpolicy_infocert_idsESS_CERT_IDissuer_serialESS_ISSUER_SERIALTS_RESPtokenstatus_infoTS_STATUS_INFOfailure_infotextstatusTS_TST_INFOtimeTS_ACCURACYmicrosmillissecondsTS_REQcert_reqnoncepolicy_idmsg_imprintTS_MSG_IMPRINThashed_msghash_algoQ3QRQhRQ@  QP Q Q QXUQ Q Q R Q@  QQP  ܼ QlP PQ  OQ $XU8S (tQlQ dQTQ T DQP 8Q0 0Q` TtT (QUQ ܼ TQQ UPP Ppq XUP.\crypto\ts\ts_asn1.c1024153620483072409661448192.\crypto\srp\srp_lib.c.\crypto\srp\srp_vfy.cPHlVRSDS/f;ApD:\CFILES\Projects\WinSSL\openssl-1.0.1c\out32dll\libeay32.pdb  ] q   2   8ZZ  (XH[ X[ $Z[  X^ TX b< j[R[z[&[[ZZZZZZZ<[`````n`b`P`@`0``aa&a@aVa^a|aaaaaa|`"```____\$\.\8\F\R\`\h\p\x\\\\\\\\\\\\\]]]$].]6]@]J]R]\]f]n]x]]]]]]]]]]]]]]]^^^"^.^8^B^L^V^`^j^r^|^^^^^^^^^ __&_4_D_V_l_____\\[[[[  ts47 poWS2_32.dllDeleteDCDeleteObjectGetBitmapBitsBitBltGetObjectAwSelectObject/CreateCompatibleBitmapGetDeviceCaps0CreateCompatibleDC1CreateDCAGDI32.dllDeregisterEventSourceReportEventARegisterEventSourceAADVAPI32.dllGetUserObjectInformationWhGetProcessWindowStation#GetDesktopWindowMessageBoxAUSER32.dlli_snprintffstrtoulJsscanfgetenvwcsstr _vsnprintfxvfprintf__iob_func|_exit7raisefree:reallocmalloc&memcpyr_localtime32_time32*memset_gmtime32_strnicmp_stricmp[strncpyp_errno(memmove5_read_writeisxdigitisdigitfprintfatoiFsprintfastrstrfputsfcloseferrorfreadfwritefflushfopenf_setmode_filenoftellfeoffseekfgetsl_wfopenNstrchr,perror_ftime325qsortOstrcmp_stat325_chmod_fdopen_openTstrerrorisalnumisspacertolowerZstrncmpisupper_strrchrexitestrtol$memchrCsignal_getch.printfMSVCR90.dlls_except_handler4_commonj_encode_pointer_malloc_crtk_encoded_null`_decode_pointer_initterm_initterm_e_amsg_exit _adjust_fdivj__CppXcptFilterK_crt_debugger_hook__clean_type_info_names_internal_unlock__dllonexitv_lock_onexitExitProcessEGetProcAddressGetModuleHandleAGetCurrentThreadIdGetLastErrorGetVersionGetFileTypedGetStdHandleCFindNextFileA2FindFirstFileA.FindClosebFreeLibrary<LoadLibraryARCloseHandlesSetLastErrorgMultiByteToWideCharGetTickCountQueryPerformanceCounterGetCurrentProcessIdGlobalMemoryStatusGetVersionExAVFlushConsoleInputBufferInterlockedExchangeSleepInterlockedCompareExchangeTerminateProcessGetCurrentProcessUnhandledExceptionFilterSetUnhandledExceptionFilterIsDebuggerPresentyGetSystemTimeAsFileTimeKERNEL32.dll;O^DHbX\8 8( h(  p PPj `pm p  @ P`@0`MQRpQw`v ]@]OPIO`O`LP0@v[eg0hO0NK0JPp[_U`Z hH 0ii0Jrv s` p PPP @r0.@0ppP. u plpB @DD`DpH0; : 9 : < P/-0`%P@P!#@&47060$%p`[S`YS\ZZ@fi&`8`9P@9:pp00U?HP6 \pP@p; 39`9@8"$"%8:00++)!p%!P$89.{pzP@P P }{P}0jPkPD`DDpD lAABpLPK K0K@KJKKAoyyllp:pFFFFxpwprrrrP>@:@xPxX WPX VpP\@\\\`0 `@@@0 JrbZ>;=0;; ;G?EpIJ^I`0o kkpe gpdcOoik@e|fpd`c``o jle`g@qecM`oikegqdc f f e e d d c pc  c b d d a a b pb e e `a a a PP Ph0mce od@q@uv@     `yzx`ywu`ytp\ _ [ P^ X ] 33>>KK0U U UU`@U``V0@@T 0[0[pP0 `  BB@ Bp@ P CpCP`C nG0p@6706`6=p= >>P=0gPg`@0TT<<pp055 pMPM КpP`   @Mttpp `0  pJ`DpG`Ia00@0P@д@@" Q`  \\`` e Pe Pd 0c b c a 0b d @ @_ ^  @M3`>KPUT CpB5=0= pT<P5@X P8@P<67`7Q@ b9"`&P'baa@_ 0_ ! SpP`PЮp`!Q    \\ ` e pe pd Pc b c a Pb d ` a@a   ` M3>KpUU@CB:6=P= T<p5` p~``v`P@ `p@@``@0  пP r @f g `g 0l i j k r v Pm p n zh`h @ 0hh@  P ` rP-@ 0p0Q!  ww0w w p0Pf` p>p?>CWwu кJ>=0@00P`JP=`ywpx@0pP0P`P0o `r 0o p +)*P) P @` P ` r0 0uPLkl@lplpo mpr P 0  0 >>@kPo! ! P ]p] 0fff`f6 `7 `/ 7 . / 3 3 9 < < > 0@ = @ pC H ! 0]! P]-Э` R R @R PR R R R R 0] d 0d PD D Zpx wPU ` j i j 0j `c > 3 F `> j  z / Pz@p P ,,--0 p @ Ш  ` @ P P p @ @ ` p 0  P ` Ц Ч  p 0 0 ` /0/07777 p P1@k k l l pk Pk k k P0 `@pPе22p222021@2o o Pm n @o l p) q @q Pq q q q q q 0r Pr r `r r r r r 0s Ps s `s ( @( ( ( ) ? ""@#Py` P4 Ђ @ P Ё = `& 8 6 p`@>  Pu u 0 v u0  uut@vP P P 7x|NNP9 0=  R 0P@pUZWZZXS`WW0 z@0` M@ q Pp N@ `Q O ' @MЦ@ p@pq% i` jp  9hMp:uj` |8 o( q @Q N` ` o` Q p}M ) Ц q`4 N p%pPr@ 8  9`   08 qЦ @Pq % P R ` hP `j0 '@ PiQ j0R @ PQ  N p #p@N@|P@  ` ` `  p @ P (`,p"'!+@)%p|xs0ppz|P@|t{p p     Q P`00@p @0pPP@ `ЪP@ p `p'0( &R dPdM0PB;;<:: q; B0=C C:0C::@7 ; 6 8 7 = p7 P< 7 9 p; 7 6 P0>I   930N PN F @=0 ` P` @0`22 22U`TTSPXw   3 м0 OO:: p kP 0 ` `k 0 Ц R 0 ` p  ` p P q@ kP    Pb 0tP` p P5 c K p , p p  `20 0y( `  `T@ b S 0/  l a qb ` `d qb .p Q @ N @J a `+3  0c P0 Q + 8  p5 `9 <p0 P 0 prp`k K u @r `0? ` @ a p.  '0 @f M b  i `/[@RXd  P8  pM   aP10 P /@  0bd @k  Q @ pbP0 @ `a T 5`a@e  j `c  c  @ pR a ЦR ) ` ` b ` jp `C 8 ai@ P  `  'P1 3p-  pW 0 Z 0@T {Pb Np 0a@`AP> p Pd pN p  `  @: P` 0 b 1 a   0  - p @a@p u `b Lc `@ r@@" R @a0p`S gP_ P  q@ 0   ]pR `R @b _ ` K` Q  b ` P P* @ @ @5 ww0. 0 a@  c 9_ <8 pT p<PT  qa `!` S  }@Y0 @0 p ` p W    @ x =`0d Q  0    0H V `8 u5   @ b +    ` Q Ps  P 5  ( p! P0op- X oPZ`B0R  . ) `* `w @- R 0S `X H  `` Pv0   @3 #y_ ` 0-  ` p 1  `  c p c S P 8 ? a b 0l c `a0 Ppq ` iZ` aap7` / d VpQ p\T Pp !PaT @ T a Pt3 0pa0 00 b q s P.  @0 <`` pT  T `_ 3 `E 0d p0  pa  Pf Pa  K b_ 8 tPb p* 0  a @k6 ` p @; `b a` G c @ 00` c @0 Px 3 @S d PR>e (  @d - v?` @. @ @K 0 Pc p 4  ``J ` d ` Cr   8._ = S @ R  p L T  0 ` Y0a W 3 ``  p `/ , жp? @ S 0qG P-0b  W  0R :T 0X V R `R R @R  qV Ц`  0cb ^ ^ 0> X пbZY YZYZV B X B pLPKb E$GMpGL`Y@Y@Z@H [0pKP Z B[B`K0H@P pt  @ p ` w y0yxx `0  0Ъ `   . @ ``rPPd `@ 0m O p` < Ђ 0R  q7G0P`0B`kl@   Bp  P `m:f x0r ` 0B 1@p  @` pf 7m q ` p p4 z R @n Gpk pl`?0R `r7 H0pkm`;`400  Ц  kQ pl@ p .P@ p@00 @a l @ Ц RP  i@k`0# нk  pn@! 0_ 0P Pkn77` pP4,p|zn@p0D`# Q0m3 f `   p F  s{p  | C@APC PmlR `@ H Х p rQ 0P e 6 <0@|S@l0R `79 C `z0 4P4 7O Px `6n 6 0k i 0rf  0e ` Э @@@{Pe e P P \Х0p-8@V2P222@81313MMOOMMNNOO0N NNNO0PNNN ЦJJ J J q pIЦ`` ЦI R  qP q k R Prd@@op oPoY0opK `! $ " `35p4p04 4% p  0 ` @  0 p  0 @ `   `   0 0% ` $ p 0   @   P q qp p P `  0 ' 0 P    0p% % @ & @ 0 p ` P% `  & P  00pH#g P Ѓ@ :  @ `   P ` 0g @ P@0 R `k P` p 0 P @ P pp R @ @ ``  ] `0 q`   P P R P A Pg q@    Ц; 0R  ` S PS o  З  ` PЙ 00 YЦp^@@S ` 0m Н ` 8 P p`!J @   q@   0   F  0p  y p Ц 0Y7  P R p @   Ц  `  Ф 4 `  p @ @  qlP- 0< `f y  j X` ] n  R p ` V @ ` ЦЦ XЦ P 0 ` `0R VЛ  P S 0 ]` 0l 0 ` ` Л 0R ` mp П @ k @   @  0R @  P q ] P  0 0 pq 0] R P ` R `   p P!0  p @ pT ` ` 0T `P@0 @ 0 AІ  Jp `  @ 0Q" ! `p`@40T S :0@0 @FFFCpE P  P p p 0 p `Z`Y@[ Pe0ec0 j j0c Pcj0@p а Ќ`:Ю М P`` :2 . - 00i0pk'7CSfr3G_s(<Pfw*Jbx .?Ran|1G]l2Jb| 0F`v 2G_o # 5 H Y g w           : T b p       ! 2 E ] o          6 M a o           ! / A R c q          &6EXiz"0@JWdv/BVm-AUi{ 1KT`l|,@NWdz $/<L\dp} )9LWckv!6EUcv&4>Ri,BU`lw*:N^r!2BRiz#-7APYft{1H_v'2CN_o 6LWcn%09ETiq " * 2 : G T a t           !!(!5!@!Y!p!!!!!!!!!!""0"D"^"x""""""#.#E#_#####$ $@$\$s$$$$$$ % %>%Z%x%%%%%%%%&!&9&J&d&q&z&&&&&&&&''&'0'H']'n'''''''''(&(/(@(U(q(((((( )&)@)K)Z)q)))))**5*R*n*y*********+ ++5+E+V+f+}++++++ ,,%,2,B,[,t,,,,,,,,-#-6-J-^-r------.!.7.M._.u......./,/B/]/s//////00,0?0V0o000000001(1D1Y1l1~1111112?2X2k222222303O3l333333344&474K4_4r444444 55/5>5S5c5z55555646K6n6666677)7:7P7e7}77777778!8/8?8Q8a8v8888888899)979D9Q9^9i9y999999999 ::':;:Q:d:x::::::::::;.;=;Q;X;f;|;;;;;;;;;<<&<5<E<Z<m<<<<<<<<<<===(=@=[=r==========>>>'>2>@>P>c>s>>>>>>>>>???!?8?I?a?p?????????? @@!@2@J@[@q@@@@@@@@@AA/AFA_AqAAAAAAAAABB0BCBVBkBzBBBBBBBB C"C:CPChCCCCCCDD3DQDdDqDDDDDDEE2EIElE~EEEEEEEEFF/FDFUFpFFFFFFFFG%G6GGG^GtGGGGGGGHHH,H:HcHHHHHHHI$I1I>IQIcIvIIIII$JLJeJ{JJJJJJJJKK)K5KEK\KjKvKKKKKKKKKL"L7LPLfL}LLLLLL M$M7MJMbM}MMMMMMMN'N7NQNrNNNNNNO&O>OUOaO}OOOOOOOP*P5POPbPvPPPPPPPQ(QBQ[QsQQQQQR%R=RVRnRRRRRRRRSS%S8SMSfSySSSSSST!TZSZgZ{ZZZZZZZ["[;[Y[i[z[[[[[[[ \ \7\D\W\g\x\\\\\\\ ]]4]J]a]|]]]]]]]^0^C^V^n^^^^^^_%_7_P_a_x________ ` `/`A`R`b`r`````````aa)a;aOabasaaaaaaaabb&b8bKbbbrbbbbbbbbcc(c5cFcRc^clcyccccccccdd*d;dMdgd~dddddd ee=eWekeeeeeee f f3fJf]fpfffffffg+g;gLgZggggggggggh'h8hNhchqhhhhhhhhi i8iXiditiiiiiiiij0jGjajzjjjjjjk)kJkfkkkkkkkkl)l:lLlalslllllllllm2m@mMm[mkmzmmmmmmmmnn(n8nHnXnhnynnnnnnnnoo(o;oLo\olo|ooooooooo p#p8pMpbpxpppppppq)q>qSqaqqqqqqqqqqqqqrr(r:rKr\rlr~rrrrrrrrrr ss(s7sDsQsYsasmsvssssssssssst"t/t?tLtYtktst|tttttttttuu&u7uIuZuku}uuuuuuvv.vAvUvZvkvyvvvvvvvvv w!w3wFwVwdwswwwwwwww xx.x?xQxcxsxxxxxxxxx yy/y?yPyXy\yfyoy}yyyyyyyyyyyy zz4z@zNz]zkzvzzzzzzzzz {${?{S{e{x{{{{{{{ |&|9|N|a|r|||||||||}}!}1}@}N}[}k}w}}}}}}}}}}} ~~!~0~;~G~S~o~~~~~~#Fcu"1J^u΀ #2BTdu΁5VqЂ 2CUfuσ#6J^pӄ<[ąޅ !8HZkņԆ-<Qhʇ&<K`yʈۈ(Hjzω1@Rdsϊ݊*BQ^lzËы /=JYľڌ (?Sf~Ǎ֍&=SguÎЎ*A]wŏ؏ %=Xrΐ%=Rfˑۑ#ARg͒ #1K]v“ړ*Oc~Ҕ ";Wrҕ/@O_tÖҖ 2IYuƗח$0?Skwʘݘ  3IVgv̙ޙ "5G^mɚܚ$7HZq›՛,H^xȜ؜1G]t۝,@Vdxў +:KYv̟,5?Oezʠ٠&3HUn̡ܡ)?O]lӢ#6Urãϣأ"7FPbwäӤ/;?KWaqȥ٥ 3DUes}¦Ҧ-Hbҧ8Wpɨݨ*9LUpy۩ +?LPU`jyǪӪ '4@Q_ir˫֫ 3GR]lŬެ #2?JVk|ӭܭ5M]tծ  2Uoӯ(?Tg{ְ%7BR^rȱݱ(=P[lв.EVnƳ%?[v˴&;GYq̵ߵ3JZoȶ5Jf|Ʒ۷-Fbx¸׸,?Qizȹչ.CWh}к !)?UdzŻٻ&9Ndyļټ%:OVdoνݽ.?Wpžپ-=Q`oȿܿ7H^w+=Qgv,B_| 2Kfy&7I^r):Rj/H`w/BVr&4Id4Rp (<Wr %@Zt $?_z.EVk}0CTfy+;H_m%1>M_q+@Xj -Mky9Ys:]q";To"5K[q&=Rkz,:FSq.D[w$DVn"3<R`p| %?]x)<Mbr+EM]m/Lm )7J\m  5Kb}#;Sk~ 0Fav%<Wq.EZt'@Zx4Oey$6BO]k|#5BO]hy 0D]t,?M[m&<Th0APcu ,=Mcx#5FViy2AQbs &3CN^r):Phv2ATr*;Pdp(7EQap#6DQct +<IVco&4K_p$5Iby 1DR`y4H_k~#4CVht0@Vk(9I\l}%4DUfy &6AQex+<Rjx7Ok"0?Rdr*<FRbu,?NWfv 0>R`p}2CYi},6?LT^es   % 1 ? O Z f r }         ! ( 0 ; C M Z a m t {               b   ! XY #= U<$ E   s" M   A>a RwM y k < ; QEg{ b'  , 3~ x* W } \  ^   ` K34[56   7+ E0 q &  ! 3 D > ^ )  _ ?  >O J"#z + $% p   & @ i '()*+,-a 2$iLW3 q56) y p 789:;<>?@ABD=%&FGHIJK 49MN8N O PQRYS SWQUTUVWXYZ [\^_ac>d'efghijkM l x  R mnn f [    % DX D z Toopq ighj rs^uwv! xyz{|}m~} , {tF  j  ` l/ N < k  t " u8-  2          {0rayz3n~uct1o4}m2q|pfhsdvxjkHGwxyz_y z { }  u n  x p v r | m t w  4 OD?/>('# &+ ll  "*,-.)%s q p r >  n& i o$! qr mn k o  ps       ! '_b()*+ac]^`eZ[q  X r   v\5467Nffb_d  h 9 * b=   q ; m  #~ B o VW (J W yQ| g  + * L< 4z n P L  d  ~5 D     ( ]  ; %I N - e G r P aY E s p K\ O 7 ) #  k  2 Ri   2 )$ g { v B n S C  S a : M   ' ^ c 6+(9H @ F 8 ` +    0 g dZ e =I L -; | H     s :  d `o x Y b  8 d h p  7 } 8( e 3 h   r \9  @ j|&3c &/_ 20:^ :L< $;=p!) b _  \ w $ / m c M   l E 7*1Y q)T+!%&ZMpBy(QuUi Q !}J7QJh -'#{.CBVRO8 n B [u.V]tk_& IMn:y 'yT !#$n  S  R  -  /   %&'()* + ,-./ 0 123 456789:;<=>?@ BCNDEFGHIIMKFJKL F   2! 5 D mt    2N A j  0 ~ T  I    S Q ?  / RSTUVWXY    ZP [lj\k ]hi^_ LOz PQRS`bcdeqfghijkMlm  X =  U   \ + * W 6 ] H u ] " * f _ P C < E J   X 8 Pm   3 d & ; 1  . 1 6 o V  [  ' 2 P h V R } l   y U ( , 9   v , U [ % RS C H  s B   CA?  { y  w unopqrstuvwxyz {|}~b/!| 'O   b4:^t.owq _ \uD9g    7  6  o  Z F  \ N { # *0G " x '    /  A "5[kq01rfsaetuviW 2j4h`$ " 'M  :  @ lZ  Xa pv   YY  ;:6 Le76Zo      5   EGCJDHL . E O T 0Z cl^g@]3l 2/4 .,*0?GaxSz)c~Xs]:hl1PjClps_rY)Unf6F=m AW1+i->kAz%7:h=Er@Z<v%^<  H K 5  G  ( X 5  . K ! -  s L c u  C e  T L `  ; nm4f,` gB o m } nh r   UV W   c      V "; .    7. Nj !"#$%&'()*+,-./0123456r 789:yw;<=>?@ABCDEF: GHI~ | JK L MNOPQv RSt)Fz8A TB UXV 9 VRWb TOX> YZ [P\]^_5`a bcdefghitQ j/ k lm  K n  0    opqP5rst[u #  = v wCv 1 Jl T S F \ U  ![xz {"V| }~d e c O "   i * w 4 G  N u<8  eZ  ? ] % Z w   i p  3  "#$%& V I  w. Bs J G f 4 1 Kg [t w { C xs =;}i?A ,8  X` z Rq  t |  T  S 2 O J W & 8 m /zv v~#  g 9-1aIOd~*g|`BqT% ./0u x 1D2 45|678dH9df : ;<:< go=>@>?@A9B"  { F t[ F w $ k 7 @  CDGE  D Q y I  xt FGHIJK LMNOPQz{}!  RSTUVWe =@,0$oX;#XY]ZS9[\]^_`Qabcdefghijklm, 6nopqrstuvwxyz{|}~' $ } wA  >c    j uvtLIBEAY32.dllACCESS_DESCRIPTION_freeACCESS_DESCRIPTION_itACCESS_DESCRIPTION_newAES_bi_ige_encryptAES_cbc_encryptAES_cfb128_encryptAES_cfb1_encryptAES_cfb8_encryptAES_ctr128_encryptAES_decryptAES_ecb_encryptAES_encryptAES_ige_encryptAES_ofb128_encryptAES_optionsAES_set_decrypt_keyAES_set_encrypt_keyAES_unwrap_keyAES_wrap_keyASN1_ANY_itASN1_BIT_STRING_checkASN1_BIT_STRING_freeASN1_BIT_STRING_get_bitASN1_BIT_STRING_itASN1_BIT_STRING_name_printASN1_BIT_STRING_newASN1_BIT_STRING_num_ascASN1_BIT_STRING_setASN1_BIT_STRING_set_ascASN1_BIT_STRING_set_bitASN1_BMPSTRING_freeASN1_BMPSTRING_itASN1_BMPSTRING_newASN1_BOOLEAN_itASN1_ENUMERATED_freeASN1_ENUMERATED_getASN1_ENUMERATED_itASN1_ENUMERATED_newASN1_ENUMERATED_setASN1_ENUMERATED_to_BNASN1_FBOOLEAN_itASN1_GENERALIZEDTIME_adjASN1_GENERALIZEDTIME_checkASN1_GENERALIZEDTIME_freeASN1_GENERALIZEDTIME_itASN1_GENERALIZEDTIME_newASN1_GENERALIZEDTIME_printASN1_GENERALIZEDTIME_setASN1_GENERALIZEDTIME_set_stringASN1_GENERALSTRING_freeASN1_GENERALSTRING_itASN1_GENERALSTRING_newASN1_IA5STRING_freeASN1_IA5STRING_itASN1_IA5STRING_newASN1_INTEGER_cmpASN1_INTEGER_dupASN1_INTEGER_freeASN1_INTEGER_getASN1_INTEGER_itASN1_INTEGER_newASN1_INTEGER_setASN1_INTEGER_to_BNASN1_NULL_freeASN1_NULL_itASN1_NULL_newASN1_OBJECT_createASN1_OBJECT_freeASN1_OBJECT_itASN1_OBJECT_newASN1_OCTET_STRING_NDEF_itASN1_OCTET_STRING_cmpASN1_OCTET_STRING_dupASN1_OCTET_STRING_freeASN1_OCTET_STRING_itASN1_OCTET_STRING_newASN1_OCTET_STRING_setASN1_PCTX_freeASN1_PCTX_get_cert_flagsASN1_PCTX_get_flagsASN1_PCTX_get_nm_flagsASN1_PCTX_get_oid_flagsASN1_PCTX_get_str_flagsASN1_PCTX_newASN1_PCTX_set_cert_flagsASN1_PCTX_set_flagsASN1_PCTX_set_nm_flagsASN1_PCTX_set_oid_flagsASN1_PCTX_set_str_flagsASN1_PRINTABLESTRING_freeASN1_PRINTABLESTRING_itASN1_PRINTABLESTRING_newASN1_PRINTABLE_freeASN1_PRINTABLE_itASN1_PRINTABLE_newASN1_PRINTABLE_typeASN1_SEQUENCE_ANY_itASN1_SEQUENCE_itASN1_SET_ANY_itASN1_STRING_TABLE_addASN1_STRING_TABLE_cleanupASN1_STRING_TABLE_getASN1_STRING_cmpASN1_STRING_copyASN1_STRING_dataASN1_STRING_dupASN1_STRING_freeASN1_STRING_get_default_maskASN1_STRING_lengthASN1_STRING_length_setASN1_STRING_newASN1_STRING_printASN1_STRING_print_exASN1_STRING_print_ex_fpASN1_STRING_setASN1_STRING_set0ASN1_STRING_set_by_NIDASN1_STRING_set_default_maskASN1_STRING_set_default_mask_ascASN1_STRING_to_UTF8ASN1_STRING_typeASN1_STRING_type_newASN1_T61STRING_freeASN1_T61STRING_itASN1_T61STRING_newASN1_TBOOLEAN_itASN1_TIME_adjASN1_TIME_checkASN1_TIME_freeASN1_TIME_itASN1_TIME_newASN1_TIME_printASN1_TIME_setASN1_TIME_set_stringASN1_TIME_to_generalizedtimeASN1_TYPE_cmpASN1_TYPE_freeASN1_TYPE_getASN1_TYPE_get_int_octetstringASN1_TYPE_get_octetstringASN1_TYPE_newASN1_TYPE_setASN1_TYPE_set1ASN1_TYPE_set_int_octetstringASN1_TYPE_set_octetstringASN1_UNIVERSALSTRING_freeASN1_UNIVERSALSTRING_itASN1_UNIVERSALSTRING_newASN1_UNIVERSALSTRING_to_stringASN1_UTCTIME_adjASN1_UTCTIME_checkASN1_UTCTIME_cmp_time_tASN1_UTCTIME_freeASN1_UTCTIME_itASN1_UTCTIME_newASN1_UTCTIME_printASN1_UTCTIME_setASN1_UTCTIME_set_stringASN1_UTF8STRING_freeASN1_UTF8STRING_itASN1_UTF8STRING_newASN1_VISIBLESTRING_freeASN1_VISIBLESTRING_itASN1_VISIBLESTRING_newASN1_add_oid_moduleASN1_bn_printASN1_check_infinite_endASN1_const_check_infinite_endASN1_d2i_bioASN1_d2i_fpASN1_digestASN1_dupASN1_generate_nconfASN1_generate_v3ASN1_get_objectASN1_i2d_bioASN1_i2d_fpASN1_item_d2iASN1_item_d2i_bioASN1_item_d2i_fpASN1_item_digestASN1_item_dupASN1_item_ex_d2iASN1_item_ex_freeASN1_item_ex_i2dASN1_item_ex_newASN1_item_freeASN1_item_i2dASN1_item_i2d_bioASN1_item_i2d_fpASN1_item_ndef_i2dASN1_item_newASN1_item_packASN1_item_printASN1_item_signASN1_item_sign_ctxASN1_item_unpackASN1_item_verifyASN1_mbstring_copyASN1_mbstring_ncopyASN1_object_sizeASN1_pack_stringASN1_parseASN1_parse_dumpASN1_primitive_freeASN1_primitive_newASN1_put_eocASN1_put_objectASN1_seq_packASN1_seq_unpackASN1_signASN1_tag2bitASN1_tag2strASN1_template_d2iASN1_template_freeASN1_template_i2dASN1_template_newASN1_unpack_stringASN1_verifyAUTHORITY_INFO_ACCESS_freeAUTHORITY_INFO_ACCESS_itAUTHORITY_INFO_ACCESS_newAUTHORITY_KEYID_freeAUTHORITY_KEYID_itAUTHORITY_KEYID_newBASIC_CONSTRAINTS_freeBASIC_CONSTRAINTS_itBASIC_CONSTRAINTS_newBF_cbc_encryptBF_cfb64_encryptBF_decryptBF_ecb_encryptBF_encryptBF_ofb64_encryptBF_optionsBF_set_keyBIGNUM_itBIO_acceptBIO_asn1_get_prefixBIO_asn1_get_suffixBIO_asn1_set_prefixBIO_asn1_set_suffixBIO_callback_ctrlBIO_clear_flagsBIO_copy_next_retryBIO_ctrlBIO_ctrl_get_read_requestBIO_ctrl_get_write_guaranteeBIO_ctrl_pendingBIO_ctrl_reset_read_requestBIO_ctrl_wpendingBIO_debug_callbackBIO_dgram_non_fatal_errorBIO_dumpBIO_dump_cbBIO_dump_fpBIO_dump_indentBIO_dump_indent_cbBIO_dump_indent_fpBIO_dup_chainBIO_f_asn1BIO_f_base64BIO_f_bufferBIO_f_cipherBIO_f_mdBIO_f_nbio_testBIO_f_nullBIO_f_reliableBIO_fd_non_fatal_errorBIO_fd_should_retryBIO_find_typeBIO_freeBIO_free_allBIO_get_accept_socketBIO_get_callbackBIO_get_callback_argBIO_get_ex_dataBIO_get_ex_new_indexBIO_get_host_ipBIO_get_portBIO_get_retry_BIOBIO_get_retry_reasonBIO_gethostbynameBIO_getsBIO_indentBIO_int_ctrlBIO_method_nameBIO_method_typeBIO_newBIO_new_CMSBIO_new_NDEFBIO_new_PKCS7BIO_new_acceptBIO_new_bio_pairBIO_new_connectBIO_new_dgramBIO_new_fdBIO_new_fileBIO_new_fpBIO_new_mem_bufBIO_new_socketBIO_nextBIO_nreadBIO_nread0BIO_number_readBIO_number_writtenBIO_nwriteBIO_nwrite0BIO_popBIO_printfBIO_ptr_ctrlBIO_pushBIO_putsBIO_readBIO_s_acceptBIO_s_bioBIO_s_connectBIO_s_datagramBIO_s_fdBIO_s_fileBIO_s_memBIO_s_nullBIO_s_socketBIO_setBIO_set_callbackBIO_set_callback_argBIO_set_cipherBIO_set_ex_dataBIO_set_flagsBIO_set_tcp_ndelayBIO_snprintfBIO_sock_cleanupBIO_sock_errorBIO_sock_initBIO_sock_non_fatal_errorBIO_sock_should_retryBIO_socket_ioctlBIO_socket_nbioBIO_test_flagsBIO_vfreeBIO_vprintfBIO_vsnprintfBIO_writeBN_BLINDING_convertBN_BLINDING_convert_exBN_BLINDING_create_paramBN_BLINDING_freeBN_BLINDING_get_flagsBN_BLINDING_get_thread_idBN_BLINDING_invertBN_BLINDING_invert_exBN_BLINDING_newBN_BLINDING_set_flagsBN_BLINDING_set_thread_idBN_BLINDING_thread_idBN_BLINDING_updateBN_CTX_endBN_CTX_freeBN_CTX_getBN_CTX_initBN_CTX_newBN_CTX_startBN_GENCB_callBN_GF2m_addBN_GF2m_arr2polyBN_GF2m_modBN_GF2m_mod_arrBN_GF2m_mod_divBN_GF2m_mod_div_arrBN_GF2m_mod_expBN_GF2m_mod_exp_arrBN_GF2m_mod_invBN_GF2m_mod_inv_arrBN_GF2m_mod_mulBN_GF2m_mod_mul_arrBN_GF2m_mod_solve_quadBN_GF2m_mod_solve_quad_arrBN_GF2m_mod_sqrBN_GF2m_mod_sqr_arrBN_GF2m_mod_sqrtBN_GF2m_mod_sqrt_arrBN_GF2m_poly2arrBN_MONT_CTX_copyBN_MONT_CTX_freeBN_MONT_CTX_initBN_MONT_CTX_newBN_MONT_CTX_setBN_MONT_CTX_set_lockedBN_RECP_CTX_freeBN_RECP_CTX_initBN_RECP_CTX_newBN_RECP_CTX_setBN_X931_derive_prime_exBN_X931_generate_XpqBN_X931_generate_prime_exBN_addBN_add_wordBN_asc2bnBN_bin2bnBN_bn2binBN_bn2decBN_bn2hexBN_bn2mpiBN_bntest_randBN_clearBN_clear_bitBN_clear_freeBN_cmpBN_copyBN_dec2bnBN_divBN_div_recpBN_div_wordBN_dupBN_expBN_freeBN_from_montgomeryBN_gcdBN_generate_primeBN_generate_prime_exBN_get0_nist_prime_192BN_get0_nist_prime_224BN_get0_nist_prime_256BN_get0_nist_prime_384BN_get0_nist_prime_521BN_get_paramsBN_get_wordBN_hex2bnBN_initBN_is_bit_setBN_is_primeBN_is_prime_exBN_is_prime_fasttestBN_is_prime_fasttest_exBN_kroneckerBN_lshiftBN_lshift1BN_mask_bitsBN_mod_addBN_mod_add_quickBN_mod_expBN_mod_exp2_montBN_mod_exp_montBN_mod_exp_mont_consttimeBN_mod_exp_mont_wordBN_mod_exp_recpBN_mod_exp_simpleBN_mod_inverseBN_mod_lshiftBN_mod_lshift1BN_mod_lshift1_quickBN_mod_lshift_quickBN_mod_mulBN_mod_mul_montgomeryBN_mod_mul_reciprocalBN_mod_sqrBN_mod_sqrtBN_mod_subBN_mod_sub_quickBN_mod_wordBN_mpi2bnBN_mulBN_mul_wordBN_newBN_nist_mod_192BN_nist_mod_224BN_nist_mod_256BN_nist_mod_384BN_nist_mod_521BN_nnmodBN_num_bitsBN_num_bits_wordBN_optionsBN_printBN_print_fpBN_pseudo_randBN_pseudo_rand_rangeBN_randBN_rand_rangeBN_reciprocalBN_rshiftBN_rshift1BN_set_bitBN_set_negativeBN_set_paramsBN_set_wordBN_sqrBN_subBN_sub_wordBN_swapBN_to_ASN1_ENUMERATEDBN_to_ASN1_INTEGERBN_uaddBN_ucmpBN_usubBN_value_oneBUF_MEM_freeBUF_MEM_growBUF_MEM_grow_cleanBUF_MEM_newBUF_memdupBUF_reverseBUF_strdupBUF_strlcatBUF_strlcpyBUF_strndupCAST_cbc_encryptCAST_cfb64_encryptCAST_decryptCAST_ecb_encryptCAST_encryptCAST_ofb64_encryptCAST_set_keyCBIGNUM_itCERTIFICATEPOLICIES_freeCERTIFICATEPOLICIES_itCERTIFICATEPOLICIES_newCMAC_CTX_cleanupCMAC_CTX_copyCMAC_CTX_freeCMAC_CTX_get0_cipher_ctxCMAC_CTX_newCMAC_FinalCMAC_InitCMAC_UpdateCMAC_resumeCMS_ContentInfo_freeCMS_ContentInfo_itCMS_ContentInfo_newCMS_ContentInfo_print_ctxCMS_EncryptedData_decryptCMS_EncryptedData_encryptCMS_EncryptedData_set1_keyCMS_EnvelopedData_createCMS_ReceiptRequest_create0CMS_ReceiptRequest_freeCMS_ReceiptRequest_get0_valuesCMS_ReceiptRequest_itCMS_ReceiptRequest_newCMS_RecipientInfo_decryptCMS_RecipientInfo_kekri_get0_idCMS_RecipientInfo_kekri_id_cmpCMS_RecipientInfo_ktri_cert_cmpCMS_RecipientInfo_ktri_get0_algsCMS_RecipientInfo_ktri_get0_signer_idCMS_RecipientInfo_set0_keyCMS_RecipientInfo_set0_passwordCMS_RecipientInfo_set0_pkeyCMS_RecipientInfo_typeCMS_SignedData_initCMS_SignerInfo_cert_cmpCMS_SignerInfo_get0_algsCMS_SignerInfo_get0_signer_idCMS_SignerInfo_set1_signer_certCMS_SignerInfo_signCMS_SignerInfo_verifyCMS_SignerInfo_verify_contentCMS_add0_CertificateChoicesCMS_add0_RevocationInfoChoiceCMS_add0_certCMS_add0_crlCMS_add0_recipient_keyCMS_add0_recipient_passwordCMS_add1_ReceiptRequestCMS_add1_certCMS_add1_crlCMS_add1_recipient_certCMS_add1_signerCMS_add_simple_smimecapCMS_add_smimecapCMS_add_standard_smimecapCMS_compressCMS_dataCMS_dataFinalCMS_dataInitCMS_data_createCMS_decryptCMS_decrypt_set1_keyCMS_decrypt_set1_passwordCMS_decrypt_set1_pkeyCMS_digest_createCMS_digest_verifyCMS_encryptCMS_finalCMS_get0_RecipientInfosCMS_get0_SignerInfosCMS_get0_contentCMS_get0_eContentTypeCMS_get0_signersCMS_get0_typeCMS_get1_ReceiptRequestCMS_get1_certsCMS_get1_crlsCMS_is_detachedCMS_set1_eContentTypeCMS_set1_signers_certsCMS_set_detachedCMS_signCMS_sign_receiptCMS_signed_add1_attrCMS_signed_add1_attr_by_NIDCMS_signed_add1_attr_by_OBJCMS_signed_add1_attr_by_txtCMS_signed_delete_attrCMS_signed_get0_data_by_OBJCMS_signed_get_attrCMS_signed_get_attr_by_NIDCMS_signed_get_attr_by_OBJCMS_signed_get_attr_countCMS_streamCMS_uncompressCMS_unsigned_add1_attrCMS_unsigned_add1_attr_by_NIDCMS_unsigned_add1_attr_by_OBJCMS_unsigned_add1_attr_by_txtCMS_unsigned_delete_attrCMS_unsigned_get0_data_by_OBJCMS_unsigned_get_attrCMS_unsigned_get_attr_by_NIDCMS_unsigned_get_attr_by_OBJCMS_unsigned_get_attr_countCMS_verifyCMS_verify_receiptCOMP_CTX_freeCOMP_CTX_newCOMP_compress_blockCOMP_expand_blockCOMP_rleCOMP_zlibCOMP_zlib_cleanupCONF_dump_bioCONF_dump_fpCONF_freeCONF_get1_default_config_fileCONF_get_numberCONF_get_sectionCONF_get_stringCONF_imodule_get_flagsCONF_imodule_get_moduleCONF_imodule_get_nameCONF_imodule_get_usr_dataCONF_imodule_get_valueCONF_imodule_set_flagsCONF_imodule_set_usr_dataCONF_loadCONF_load_bioCONF_load_fpCONF_module_addCONF_module_get_usr_dataCONF_module_set_usr_dataCONF_modules_finishCONF_modules_freeCONF_modules_loadCONF_modules_load_fileCONF_modules_unloadCONF_parse_listCONF_set_default_methodCONF_set_nconfCRL_DIST_POINTS_freeCRL_DIST_POINTS_itCRL_DIST_POINTS_newCRYPTO_THREADID_cmpCRYPTO_THREADID_cpyCRYPTO_THREADID_currentCRYPTO_THREADID_get_callbackCRYPTO_THREADID_hashCRYPTO_THREADID_set_callbackCRYPTO_THREADID_set_numericCRYPTO_THREADID_set_pointerCRYPTO_add_lockCRYPTO_cbc128_decryptCRYPTO_cbc128_encryptCRYPTO_ccm128_aadCRYPTO_ccm128_decryptCRYPTO_ccm128_decrypt_ccm64CRYPTO_ccm128_encryptCRYPTO_ccm128_encrypt_ccm64CRYPTO_ccm128_initCRYPTO_ccm128_setivCRYPTO_ccm128_tagCRYPTO_cfb128_1_encryptCRYPTO_cfb128_8_encryptCRYPTO_cfb128_encryptCRYPTO_cleanup_all_ex_dataCRYPTO_ctr128_encryptCRYPTO_ctr128_encrypt_ctr32CRYPTO_cts128_decryptCRYPTO_cts128_decrypt_blockCRYPTO_cts128_encryptCRYPTO_cts128_encrypt_blockCRYPTO_dbg_freeCRYPTO_dbg_get_optionsCRYPTO_dbg_mallocCRYPTO_dbg_reallocCRYPTO_dbg_set_optionsCRYPTO_destroy_dynlockidCRYPTO_dup_ex_dataCRYPTO_ex_data_new_classCRYPTO_freeCRYPTO_free_ex_dataCRYPTO_free_lockedCRYPTO_gcm128_aadCRYPTO_gcm128_decryptCRYPTO_gcm128_decrypt_ctr32CRYPTO_gcm128_encryptCRYPTO_gcm128_encrypt_ctr32CRYPTO_gcm128_finishCRYPTO_gcm128_initCRYPTO_gcm128_newCRYPTO_gcm128_releaseCRYPTO_gcm128_setivCRYPTO_gcm128_tagCRYPTO_get_add_lock_callbackCRYPTO_get_dynlock_create_callbackCRYPTO_get_dynlock_destroy_callbackCRYPTO_get_dynlock_lock_callbackCRYPTO_get_dynlock_valueCRYPTO_get_ex_dataCRYPTO_get_ex_data_implementationCRYPTO_get_ex_new_indexCRYPTO_get_id_callbackCRYPTO_get_lock_nameCRYPTO_get_locked_mem_ex_functionsCRYPTO_get_locked_mem_functionsCRYPTO_get_locking_callbackCRYPTO_get_mem_debug_functionsCRYPTO_get_mem_debug_optionsCRYPTO_get_mem_ex_functionsCRYPTO_get_mem_functionsCRYPTO_get_new_dynlockidCRYPTO_get_new_lockidCRYPTO_is_mem_check_onCRYPTO_lockCRYPTO_mallocCRYPTO_malloc_lockedCRYPTO_mem_ctrlCRYPTO_mem_leaksCRYPTO_mem_leaks_cbCRYPTO_mem_leaks_fpCRYPTO_new_ex_dataCRYPTO_nistcts128_decryptCRYPTO_nistcts128_decrypt_blockCRYPTO_nistcts128_encryptCRYPTO_nistcts128_encrypt_blockCRYPTO_num_locksCRYPTO_ofb128_encryptCRYPTO_pop_infoCRYPTO_push_info_CRYPTO_reallocCRYPTO_realloc_cleanCRYPTO_remallocCRYPTO_remove_all_infoCRYPTO_set_add_lock_callbackCRYPTO_set_dynlock_create_callbackCRYPTO_set_dynlock_destroy_callbackCRYPTO_set_dynlock_lock_callbackCRYPTO_set_ex_dataCRYPTO_set_ex_data_implementationCRYPTO_set_id_callbackCRYPTO_set_locked_mem_ex_functionsCRYPTO_set_locked_mem_functionsCRYPTO_set_locking_callbackCRYPTO_set_mem_debug_functionsCRYPTO_set_mem_debug_optionsCRYPTO_set_mem_ex_functionsCRYPTO_set_mem_functionsCRYPTO_strdupCRYPTO_thread_idCRYPTO_xts128_encryptCamellia_cbc_encryptCamellia_cfb128_encryptCamellia_cfb1_encryptCamellia_cfb8_encryptCamellia_ctr128_encryptCamellia_decryptCamellia_ecb_encryptCamellia_encryptCamellia_ofb128_encryptCamellia_set_keyDES_cbc_cksumDES_cbc_encryptDES_cfb64_encryptDES_cfb_encryptDES_check_key_parityDES_cryptDES_decrypt3DES_ecb3_encryptDES_ecb_encryptDES_ede3_cbc_encryptDES_ede3_cbcm_encryptDES_ede3_cfb64_encryptDES_ede3_cfb_encryptDES_ede3_ofb64_encryptDES_enc_readDES_enc_writeDES_encrypt1DES_encrypt2DES_encrypt3DES_fcryptDES_is_weak_keyDES_key_schedDES_ncbc_encryptDES_ofb64_encryptDES_ofb_encryptDES_optionsDES_pcbc_encryptDES_quad_cksumDES_random_keyDES_read_2passwordsDES_read_passwordDES_set_keyDES_set_key_checkedDES_set_key_uncheckedDES_set_odd_parityDES_string_to_2keysDES_string_to_keyDES_xcbc_encryptDH_OpenSSLDH_checkDH_check_pub_keyDH_compute_keyDH_freeDH_generate_keyDH_generate_parametersDH_generate_parameters_exDH_get_default_methodDH_get_ex_dataDH_get_ex_new_indexDH_newDH_new_methodDH_set_default_methodDH_set_ex_dataDH_set_methodDH_sizeDH_up_refDHparams_dupDHparams_printDHparams_print_fpDIRECTORYSTRING_freeDIRECTORYSTRING_itDIRECTORYSTRING_newDISPLAYTEXT_freeDISPLAYTEXT_itDISPLAYTEXT_newDIST_POINT_NAME_freeDIST_POINT_NAME_itDIST_POINT_NAME_newDIST_POINT_freeDIST_POINT_itDIST_POINT_newDIST_POINT_set_dpnameDSA_OpenSSLDSA_SIG_freeDSA_SIG_newDSA_do_signDSA_do_verifyDSA_dup_DHDSA_freeDSA_generate_keyDSA_generate_parametersDSA_generate_parameters_exDSA_get_default_methodDSA_get_ex_dataDSA_get_ex_new_indexDSA_newDSA_new_methodDSA_printDSA_print_fpDSA_set_default_methodDSA_set_ex_dataDSA_set_methodDSA_signDSA_sign_setupDSA_sizeDSA_up_refDSA_verifyDSAparams_dupDSAparams_printDSAparams_print_fpDSO_METHOD_beosDSO_METHOD_dlDSO_METHOD_dlfcnDSO_METHOD_nullDSO_METHOD_opensslDSO_METHOD_vmsDSO_METHOD_win32DSO_bind_funcDSO_bind_varDSO_convert_filenameDSO_ctrlDSO_flagsDSO_freeDSO_get_default_methodDSO_get_filenameDSO_get_loaded_filenameDSO_get_methodDSO_global_lookupDSO_loadDSO_mergeDSO_newDSO_new_methodDSO_pathbyaddrDSO_set_default_methodDSO_set_filenameDSO_set_methodDSO_set_name_converterDSO_up_refECDH_OpenSSLECDH_compute_keyECDH_get_default_methodECDH_get_ex_dataECDH_get_ex_new_indexECDH_set_default_methodECDH_set_ex_dataECDH_set_methodECDSA_OpenSSLECDSA_SIG_freeECDSA_SIG_newECDSA_do_signECDSA_do_sign_exECDSA_do_verifyECDSA_get_default_methodECDSA_get_ex_dataECDSA_get_ex_new_indexECDSA_set_default_methodECDSA_set_ex_dataECDSA_set_methodECDSA_signECDSA_sign_exECDSA_sign_setupECDSA_sizeECDSA_verifyECPKParameters_printECPKParameters_print_fpECParameters_printECParameters_print_fpEC_GF2m_simple_methodEC_GFp_mont_methodEC_GFp_nist_methodEC_GFp_simple_methodEC_GROUP_checkEC_GROUP_check_discriminantEC_GROUP_clear_freeEC_GROUP_cmpEC_GROUP_copyEC_GROUP_dupEC_GROUP_freeEC_GROUP_get0_generatorEC_GROUP_get0_seedEC_GROUP_get_asn1_flagEC_GROUP_get_basis_typeEC_GROUP_get_cofactorEC_GROUP_get_curve_GF2mEC_GROUP_get_curve_GFpEC_GROUP_get_curve_nameEC_GROUP_get_degreeEC_GROUP_get_orderEC_GROUP_get_pentanomial_basisEC_GROUP_get_point_conversion_formEC_GROUP_get_seed_lenEC_GROUP_get_trinomial_basisEC_GROUP_have_precompute_multEC_GROUP_method_ofEC_GROUP_newEC_GROUP_new_by_curve_nameEC_GROUP_new_curve_GF2mEC_GROUP_new_curve_GFpEC_GROUP_precompute_multEC_GROUP_set_asn1_flagEC_GROUP_set_curve_GF2mEC_GROUP_set_curve_GFpEC_GROUP_set_curve_nameEC_GROUP_set_generatorEC_GROUP_set_point_conversion_formEC_GROUP_set_seedEC_KEY_check_keyEC_KEY_clear_flagsEC_KEY_copyEC_KEY_dupEC_KEY_freeEC_KEY_generate_keyEC_KEY_get0_groupEC_KEY_get0_private_keyEC_KEY_get0_public_keyEC_KEY_get_conv_formEC_KEY_get_enc_flagsEC_KEY_get_flagsEC_KEY_get_key_method_dataEC_KEY_insert_key_method_dataEC_KEY_newEC_KEY_new_by_curve_nameEC_KEY_precompute_multEC_KEY_printEC_KEY_print_fpEC_KEY_set_asn1_flagEC_KEY_set_conv_formEC_KEY_set_enc_flagsEC_KEY_set_flagsEC_KEY_set_groupEC_KEY_set_private_keyEC_KEY_set_public_keyEC_KEY_set_public_key_affine_coordinatesEC_KEY_up_refEC_METHOD_get_field_typeEC_POINT_addEC_POINT_bn2pointEC_POINT_clear_freeEC_POINT_cmpEC_POINT_copyEC_POINT_dblEC_POINT_dupEC_POINT_freeEC_POINT_get_Jprojective_coordinates_GFpEC_POINT_get_affine_coordinates_GF2mEC_POINT_get_affine_coordinates_GFpEC_POINT_hex2pointEC_POINT_invertEC_POINT_is_at_infinityEC_POINT_is_on_curveEC_POINT_make_affineEC_POINT_method_ofEC_POINT_mulEC_POINT_newEC_POINT_oct2pointEC_POINT_point2bnEC_POINT_point2hexEC_POINT_point2octEC_POINT_set_Jprojective_coordinates_GFpEC_POINT_set_affine_coordinates_GF2mEC_POINT_set_affine_coordinates_GFpEC_POINT_set_compressed_coordinates_GF2mEC_POINT_set_compressed_coordinates_GFpEC_POINT_set_to_infinityEC_POINTs_make_affineEC_POINTs_mulEC_get_builtin_curvesEDIPARTYNAME_freeEDIPARTYNAME_itEDIPARTYNAME_newENGINE_addENGINE_add_conf_moduleENGINE_by_idENGINE_cleanupENGINE_cmd_is_executableENGINE_ctrlENGINE_ctrl_cmdENGINE_ctrl_cmd_stringENGINE_finishENGINE_freeENGINE_get_DHENGINE_get_DSAENGINE_get_ECDHENGINE_get_ECDSAENGINE_get_RANDENGINE_get_RSAENGINE_get_STOREENGINE_get_cipherENGINE_get_cipher_engineENGINE_get_ciphersENGINE_get_cmd_defnsENGINE_get_ctrl_functionENGINE_get_default_DHENGINE_get_default_DSAENGINE_get_default_ECDHENGINE_get_default_ECDSAENGINE_get_default_RANDENGINE_get_default_RSAENGINE_get_destroy_functionENGINE_get_digestENGINE_get_digest_engineENGINE_get_digestsENGINE_get_ex_dataENGINE_get_ex_new_indexENGINE_get_finish_functionENGINE_get_firstENGINE_get_flagsENGINE_get_idENGINE_get_init_functionENGINE_get_lastENGINE_get_load_privkey_functionENGINE_get_load_pubkey_functionENGINE_get_nameENGINE_get_nextENGINE_get_pkey_asn1_methENGINE_get_pkey_asn1_meth_engineENGINE_get_pkey_asn1_meth_strENGINE_get_pkey_asn1_methsENGINE_get_pkey_methENGINE_get_pkey_meth_engineENGINE_get_pkey_methsENGINE_get_prevENGINE_get_ssl_client_cert_functionENGINE_get_static_stateENGINE_get_table_flagsENGINE_initENGINE_load_builtin_enginesENGINE_load_cryptodevENGINE_load_dynamicENGINE_load_opensslENGINE_load_private_keyENGINE_load_public_keyENGINE_load_rdrandENGINE_load_rsaxENGINE_load_ssl_client_certENGINE_newENGINE_pkey_asn1_find_strENGINE_register_DHENGINE_register_DSAENGINE_register_ECDHENGINE_register_ECDSAENGINE_register_RANDENGINE_register_RSAENGINE_register_STOREENGINE_register_all_DHENGINE_register_all_DSAENGINE_register_all_ECDHENGINE_register_all_ECDSAENGINE_register_all_RANDENGINE_register_all_RSAENGINE_register_all_STOREENGINE_register_all_ciphersENGINE_register_all_completeENGINE_register_all_digestsENGINE_register_all_pkey_asn1_methsENGINE_register_all_pkey_methsENGINE_register_ciphersENGINE_register_completeENGINE_register_digestsENGINE_register_pkey_asn1_methsENGINE_register_pkey_methsENGINE_removeENGINE_set_DHENGINE_set_DSAENGINE_set_ECDHENGINE_set_ECDSAENGINE_set_RANDENGINE_set_RSAENGINE_set_STOREENGINE_set_ciphersENGINE_set_cmd_defnsENGINE_set_ctrl_functionENGINE_set_defaultENGINE_set_default_DHENGINE_set_default_DSAENGINE_set_default_ECDHENGINE_set_default_ECDSAENGINE_set_default_RANDENGINE_set_default_RSAENGINE_set_default_ciphersENGINE_set_default_digestsENGINE_set_default_pkey_asn1_methsENGINE_set_default_pkey_methsENGINE_set_default_stringENGINE_set_destroy_functionENGINE_set_digestsENGINE_set_ex_dataENGINE_set_finish_functionENGINE_set_flagsENGINE_set_idENGINE_set_init_functionENGINE_set_load_privkey_functionENGINE_set_load_pubkey_functionENGINE_set_load_ssl_client_cert_functionENGINE_set_nameENGINE_set_pkey_asn1_methsENGINE_set_pkey_methsENGINE_set_table_flagsENGINE_unregister_DHENGINE_unregister_DSAENGINE_unregister_ECDHENGINE_unregister_ECDSAENGINE_unregister_RANDENGINE_unregister_RSAENGINE_unregister_STOREENGINE_unregister_ciphersENGINE_unregister_digestsENGINE_unregister_pkey_asn1_methsENGINE_unregister_pkey_methsENGINE_up_refERR_add_error_dataERR_add_error_vdataERR_clear_errorERR_error_stringERR_error_string_nERR_free_stringsERR_func_error_stringERR_get_err_state_tableERR_get_errorERR_get_error_lineERR_get_error_line_dataERR_get_implementationERR_get_next_error_libraryERR_get_stateERR_get_string_tableERR_lib_error_stringERR_load_ASN1_stringsERR_load_BIO_stringsERR_load_BN_stringsERR_load_BUF_stringsERR_load_CMS_stringsERR_load_COMP_stringsERR_load_CONF_stringsERR_load_CRYPTO_stringsERR_load_DH_stringsERR_load_DSA_stringsERR_load_DSO_stringsERR_load_ECDH_stringsERR_load_ECDSA_stringsERR_load_EC_stringsERR_load_ENGINE_stringsERR_load_ERR_stringsERR_load_EVP_stringsERR_load_OBJ_stringsERR_load_OCSP_stringsERR_load_PEM_stringsERR_load_PKCS12_stringsERR_load_PKCS7_stringsERR_load_RAND_stringsERR_load_RSA_stringsERR_load_TS_stringsERR_load_UI_stringsERR_load_X509V3_stringsERR_load_X509_stringsERR_load_crypto_stringsERR_load_stringsERR_peek_errorERR_peek_error_lineERR_peek_error_line_dataERR_peek_last_errorERR_peek_last_error_lineERR_peek_last_error_line_dataERR_pop_to_markERR_print_errorsERR_print_errors_cbERR_print_errors_fpERR_put_errorERR_reason_error_stringERR_release_err_state_tableERR_remove_stateERR_remove_thread_stateERR_set_error_dataERR_set_implementationERR_set_markERR_unload_stringsESS_CERT_ID_dupESS_CERT_ID_freeESS_CERT_ID_newESS_ISSUER_SERIAL_dupESS_ISSUER_SERIAL_freeESS_ISSUER_SERIAL_newESS_SIGNING_CERT_dupESS_SIGNING_CERT_freeESS_SIGNING_CERT_newEVP_BytesToKeyEVP_CIPHER_CTX_block_sizeEVP_CIPHER_CTX_cipherEVP_CIPHER_CTX_cleanupEVP_CIPHER_CTX_clear_flagsEVP_CIPHER_CTX_copyEVP_CIPHER_CTX_ctrlEVP_CIPHER_CTX_flagsEVP_CIPHER_CTX_freeEVP_CIPHER_CTX_get_app_dataEVP_CIPHER_CTX_initEVP_CIPHER_CTX_iv_lengthEVP_CIPHER_CTX_key_lengthEVP_CIPHER_CTX_newEVP_CIPHER_CTX_nidEVP_CIPHER_CTX_rand_keyEVP_CIPHER_CTX_set_app_dataEVP_CIPHER_CTX_set_flagsEVP_CIPHER_CTX_set_key_lengthEVP_CIPHER_CTX_set_paddingEVP_CIPHER_CTX_test_flagsEVP_CIPHER_asn1_to_paramEVP_CIPHER_block_sizeEVP_CIPHER_do_allEVP_CIPHER_do_all_sortedEVP_CIPHER_flagsEVP_CIPHER_get_asn1_ivEVP_CIPHER_iv_lengthEVP_CIPHER_key_lengthEVP_CIPHER_nidEVP_CIPHER_param_to_asn1EVP_CIPHER_set_asn1_ivEVP_CIPHER_typeEVP_CipherEVP_CipherFinalEVP_CipherFinal_exEVP_CipherInitEVP_CipherInit_exEVP_CipherUpdateEVP_DecodeBlockEVP_DecodeFinalEVP_DecodeInitEVP_DecodeUpdateEVP_DecryptFinalEVP_DecryptFinal_exEVP_DecryptInitEVP_DecryptInit_exEVP_DecryptUpdateEVP_DigestEVP_DigestFinalEVP_DigestFinal_exEVP_DigestInitEVP_DigestInit_exEVP_DigestSignFinalEVP_DigestSignInitEVP_DigestUpdateEVP_DigestVerifyFinalEVP_DigestVerifyInitEVP_EncodeBlockEVP_EncodeFinalEVP_EncodeInitEVP_EncodeUpdateEVP_EncryptFinalEVP_EncryptFinal_exEVP_EncryptInitEVP_EncryptInit_exEVP_EncryptUpdateEVP_MD_CTX_cleanupEVP_MD_CTX_clear_flagsEVP_MD_CTX_copyEVP_MD_CTX_copy_exEVP_MD_CTX_createEVP_MD_CTX_destroyEVP_MD_CTX_initEVP_MD_CTX_mdEVP_MD_CTX_set_flagsEVP_MD_CTX_test_flagsEVP_MD_block_sizeEVP_MD_do_allEVP_MD_do_all_sortedEVP_MD_flagsEVP_MD_pkey_typeEVP_MD_sizeEVP_MD_typeEVP_OpenFinalEVP_OpenInitEVP_PBE_CipherInitEVP_PBE_alg_addEVP_PBE_alg_add_typeEVP_PBE_cleanupEVP_PBE_findEVP_PKCS82PKEYEVP_PKEY2PKCS8EVP_PKEY2PKCS8_brokenEVP_PKEY_CTX_ctrlEVP_PKEY_CTX_ctrl_strEVP_PKEY_CTX_dupEVP_PKEY_CTX_freeEVP_PKEY_CTX_get0_peerkeyEVP_PKEY_CTX_get0_pkeyEVP_PKEY_CTX_get_app_dataEVP_PKEY_CTX_get_cbEVP_PKEY_CTX_get_dataEVP_PKEY_CTX_get_keygen_infoEVP_PKEY_CTX_get_operationEVP_PKEY_CTX_newEVP_PKEY_CTX_new_idEVP_PKEY_CTX_set0_keygen_infoEVP_PKEY_CTX_set_app_dataEVP_PKEY_CTX_set_cbEVP_PKEY_CTX_set_dataEVP_PKEY_add1_attrEVP_PKEY_add1_attr_by_NIDEVP_PKEY_add1_attr_by_OBJEVP_PKEY_add1_attr_by_txtEVP_PKEY_asn1_add0EVP_PKEY_asn1_add_aliasEVP_PKEY_asn1_copyEVP_PKEY_asn1_findEVP_PKEY_asn1_find_strEVP_PKEY_asn1_freeEVP_PKEY_asn1_get0EVP_PKEY_asn1_get0_infoEVP_PKEY_asn1_get_countEVP_PKEY_asn1_newEVP_PKEY_asn1_set_ctrlEVP_PKEY_asn1_set_freeEVP_PKEY_asn1_set_paramEVP_PKEY_asn1_set_privateEVP_PKEY_asn1_set_publicEVP_PKEY_assignEVP_PKEY_base_idEVP_PKEY_bitsEVP_PKEY_cmpEVP_PKEY_cmp_parametersEVP_PKEY_copy_parametersEVP_PKEY_decryptEVP_PKEY_decrypt_initEVP_PKEY_decrypt_oldEVP_PKEY_delete_attrEVP_PKEY_deriveEVP_PKEY_derive_initEVP_PKEY_derive_set_peerEVP_PKEY_encryptEVP_PKEY_encrypt_initEVP_PKEY_encrypt_oldEVP_PKEY_freeEVP_PKEY_get0EVP_PKEY_get0_asn1EVP_PKEY_get1_DHEVP_PKEY_get1_DSAEVP_PKEY_get1_EC_KEYEVP_PKEY_get1_RSAEVP_PKEY_get_attrEVP_PKEY_get_attr_by_NIDEVP_PKEY_get_attr_by_OBJEVP_PKEY_get_attr_countEVP_PKEY_get_default_digest_nidEVP_PKEY_idEVP_PKEY_keygenEVP_PKEY_keygen_initEVP_PKEY_meth_add0EVP_PKEY_meth_copyEVP_PKEY_meth_findEVP_PKEY_meth_freeEVP_PKEY_meth_get0_infoEVP_PKEY_meth_newEVP_PKEY_meth_set_cleanupEVP_PKEY_meth_set_copyEVP_PKEY_meth_set_ctrlEVP_PKEY_meth_set_decryptEVP_PKEY_meth_set_deriveEVP_PKEY_meth_set_encryptEVP_PKEY_meth_set_initEVP_PKEY_meth_set_keygenEVP_PKEY_meth_set_paramgenEVP_PKEY_meth_set_signEVP_PKEY_meth_set_signctxEVP_PKEY_meth_set_verifyEVP_PKEY_meth_set_verify_recoverEVP_PKEY_meth_set_verifyctxEVP_PKEY_missing_parametersEVP_PKEY_newEVP_PKEY_new_mac_keyEVP_PKEY_paramgenEVP_PKEY_paramgen_initEVP_PKEY_print_paramsEVP_PKEY_print_privateEVP_PKEY_print_publicEVP_PKEY_save_parametersEVP_PKEY_set1_DHEVP_PKEY_set1_DSAEVP_PKEY_set1_EC_KEYEVP_PKEY_set1_RSAEVP_PKEY_set_typeEVP_PKEY_set_type_strEVP_PKEY_signEVP_PKEY_sign_initEVP_PKEY_sizeEVP_PKEY_typeEVP_PKEY_verifyEVP_PKEY_verify_initEVP_PKEY_verify_recoverEVP_PKEY_verify_recover_initEVP_SealFinalEVP_SealInitEVP_SignFinalEVP_VerifyFinalEVP_add_cipherEVP_add_digestEVP_aes_128_cbcEVP_aes_128_cbc_hmac_sha1EVP_aes_128_ccmEVP_aes_128_cfb1EVP_aes_128_cfb128EVP_aes_128_cfb8EVP_aes_128_ctrEVP_aes_128_ecbEVP_aes_128_gcmEVP_aes_128_ofbEVP_aes_128_xtsEVP_aes_192_cbcEVP_aes_192_ccmEVP_aes_192_cfb1EVP_aes_192_cfb128EVP_aes_192_cfb8EVP_aes_192_ctrEVP_aes_192_ecbEVP_aes_192_gcmEVP_aes_192_ofbEVP_aes_256_cbcEVP_aes_256_cbc_hmac_sha1EVP_aes_256_ccmEVP_aes_256_cfb1EVP_aes_256_cfb128EVP_aes_256_cfb8EVP_aes_256_ctrEVP_aes_256_ecbEVP_aes_256_gcmEVP_aes_256_ofbEVP_aes_256_xtsEVP_bf_cbcEVP_bf_cfb64EVP_bf_ecbEVP_bf_ofbEVP_camellia_128_cbcEVP_camellia_128_cfb1EVP_camellia_128_cfb128EVP_camellia_128_cfb8EVP_camellia_128_ecbEVP_camellia_128_ofbEVP_camellia_192_cbcEVP_camellia_192_cfb1EVP_camellia_192_cfb128EVP_camellia_192_cfb8EVP_camellia_192_ecbEVP_camellia_192_ofbEVP_camellia_256_cbcEVP_camellia_256_cfb1EVP_camellia_256_cfb128EVP_camellia_256_cfb8EVP_camellia_256_ecbEVP_camellia_256_ofbEVP_cast5_cbcEVP_cast5_cfb64EVP_cast5_ecbEVP_cast5_ofbEVP_cleanupEVP_des_cbcEVP_des_cfb1EVP_des_cfb64EVP_des_cfb8EVP_des_ecbEVP_des_edeEVP_des_ede3EVP_des_ede3_cbcEVP_des_ede3_cfb1EVP_des_ede3_cfb64EVP_des_ede3_cfb8EVP_des_ede3_ecbEVP_des_ede3_ofbEVP_des_ede_cbcEVP_des_ede_cfb64EVP_des_ede_ecbEVP_des_ede_ofbEVP_des_ofbEVP_desx_cbcEVP_dssEVP_dss1EVP_ecdsaEVP_enc_nullEVP_get_cipherbynameEVP_get_digestbynameEVP_get_pw_promptEVP_idea_cbcEVP_idea_cfb64EVP_idea_ecbEVP_idea_ofbEVP_md4EVP_md5EVP_md_nullEVP_mdc2EVP_rc2_40_cbcEVP_rc2_64_cbcEVP_rc2_cbcEVP_rc2_cfb64EVP_rc2_ecbEVP_rc2_ofbEVP_rc4EVP_rc4_40EVP_rc4_hmac_md5EVP_read_pw_stringEVP_read_pw_string_minEVP_ripemd160EVP_seed_cbcEVP_seed_cfb128EVP_seed_ecbEVP_seed_ofbEVP_set_pw_promptEVP_shaEVP_sha1EVP_sha224EVP_sha256EVP_sha384EVP_sha512EVP_whirlpoolEXTENDED_KEY_USAGE_freeEXTENDED_KEY_USAGE_itEXTENDED_KEY_USAGE_newFIPS_modeFIPS_mode_setGENERAL_NAMES_freeGENERAL_NAMES_itGENERAL_NAMES_newGENERAL_NAME_cmpGENERAL_NAME_dupGENERAL_NAME_freeGENERAL_NAME_get0_otherNameGENERAL_NAME_get0_valueGENERAL_NAME_itGENERAL_NAME_newGENERAL_NAME_printGENERAL_NAME_set0_othernameGENERAL_NAME_set0_valueGENERAL_SUBTREE_freeGENERAL_SUBTREE_itGENERAL_SUBTREE_newHMACHMAC_CTX_cleanupHMAC_CTX_copyHMAC_CTX_initHMAC_CTX_set_flagsHMAC_FinalHMAC_InitHMAC_Init_exHMAC_UpdateISSUING_DIST_POINT_freeISSUING_DIST_POINT_itISSUING_DIST_POINT_newKRB5_APREQBODY_freeKRB5_APREQBODY_itKRB5_APREQBODY_newKRB5_APREQ_freeKRB5_APREQ_itKRB5_APREQ_newKRB5_AUTHDATA_freeKRB5_AUTHDATA_itKRB5_AUTHDATA_newKRB5_AUTHENTBODY_freeKRB5_AUTHENTBODY_itKRB5_AUTHENTBODY_newKRB5_AUTHENT_freeKRB5_AUTHENT_itKRB5_AUTHENT_newKRB5_CHECKSUM_freeKRB5_CHECKSUM_itKRB5_CHECKSUM_newKRB5_ENCDATA_freeKRB5_ENCDATA_itKRB5_ENCDATA_newKRB5_ENCKEY_freeKRB5_ENCKEY_itKRB5_ENCKEY_newKRB5_PRINCNAME_freeKRB5_PRINCNAME_itKRB5_PRINCNAME_newKRB5_TICKET_freeKRB5_TICKET_itKRB5_TICKET_newKRB5_TKTBODY_freeKRB5_TKTBODY_itKRB5_TKTBODY_newLONG_itMD4MD4_FinalMD4_InitMD4_TransformMD4_UpdateMD5MD5_FinalMD5_InitMD5_TransformMD5_UpdateMDC2MDC2_FinalMDC2_InitMDC2_UpdateNAME_CONSTRAINTS_checkNAME_CONSTRAINTS_freeNAME_CONSTRAINTS_itNAME_CONSTRAINTS_newNCONF_WIN32NCONF_defaultNCONF_dump_bioNCONF_dump_fpNCONF_freeNCONF_free_dataNCONF_get_number_eNCONF_get_sectionNCONF_get_stringNCONF_loadNCONF_load_bioNCONF_load_fpNCONF_newNETSCAPE_CERT_SEQUENCE_freeNETSCAPE_CERT_SEQUENCE_itNETSCAPE_CERT_SEQUENCE_newNETSCAPE_SPKAC_freeNETSCAPE_SPKAC_itNETSCAPE_SPKAC_newNETSCAPE_SPKI_b64_decodeNETSCAPE_SPKI_b64_encodeNETSCAPE_SPKI_freeNETSCAPE_SPKI_get_pubkeyNETSCAPE_SPKI_itNETSCAPE_SPKI_newNETSCAPE_SPKI_printNETSCAPE_SPKI_set_pubkeyNETSCAPE_SPKI_signNETSCAPE_SPKI_verifyNETSCAPE_X509_freeNETSCAPE_X509_itNETSCAPE_X509_newNOTICEREF_freeNOTICEREF_itNOTICEREF_newOBJ_NAME_addOBJ_NAME_cleanupOBJ_NAME_do_allOBJ_NAME_do_all_sortedOBJ_NAME_getOBJ_NAME_initOBJ_NAME_new_indexOBJ_NAME_removeOBJ_add_objectOBJ_add_sigidOBJ_bsearch_OBJ_bsearch_ex_OBJ_cleanupOBJ_cmpOBJ_createOBJ_create_objectsOBJ_dupOBJ_find_sigid_algsOBJ_find_sigid_by_algsOBJ_ln2nidOBJ_new_nidOBJ_nid2lnOBJ_nid2objOBJ_nid2snOBJ_obj2nidOBJ_obj2txtOBJ_sigid_freeOBJ_sn2nidOBJ_txt2nidOBJ_txt2objOCSP_BASICRESP_add1_ext_i2dOCSP_BASICRESP_add_extOCSP_BASICRESP_delete_extOCSP_BASICRESP_freeOCSP_BASICRESP_get1_ext_d2iOCSP_BASICRESP_get_extOCSP_BASICRESP_get_ext_by_NIDOCSP_BASICRESP_get_ext_by_OBJOCSP_BASICRESP_get_ext_by_criticalOCSP_BASICRESP_get_ext_countOCSP_BASICRESP_itOCSP_BASICRESP_newOCSP_CERTID_dupOCSP_CERTID_freeOCSP_CERTID_itOCSP_CERTID_newOCSP_CERTSTATUS_freeOCSP_CERTSTATUS_itOCSP_CERTSTATUS_newOCSP_CRLID_freeOCSP_CRLID_itOCSP_CRLID_newOCSP_ONEREQ_add1_ext_i2dOCSP_ONEREQ_add_extOCSP_ONEREQ_delete_extOCSP_ONEREQ_freeOCSP_ONEREQ_get1_ext_d2iOCSP_ONEREQ_get_extOCSP_ONEREQ_get_ext_by_NIDOCSP_ONEREQ_get_ext_by_OBJOCSP_ONEREQ_get_ext_by_criticalOCSP_ONEREQ_get_ext_countOCSP_ONEREQ_itOCSP_ONEREQ_newOCSP_REQINFO_freeOCSP_REQINFO_itOCSP_REQINFO_newOCSP_REQUEST_add1_ext_i2dOCSP_REQUEST_add_extOCSP_REQUEST_delete_extOCSP_REQUEST_freeOCSP_REQUEST_get1_ext_d2iOCSP_REQUEST_get_extOCSP_REQUEST_get_ext_by_NIDOCSP_REQUEST_get_ext_by_OBJOCSP_REQUEST_get_ext_by_criticalOCSP_REQUEST_get_ext_countOCSP_REQUEST_itOCSP_REQUEST_newOCSP_REQUEST_printOCSP_REQ_CTX_add1_headerOCSP_REQ_CTX_freeOCSP_REQ_CTX_set1_reqOCSP_RESPBYTES_freeOCSP_RESPBYTES_itOCSP_RESPBYTES_newOCSP_RESPDATA_freeOCSP_RESPDATA_itOCSP_RESPDATA_newOCSP_RESPID_freeOCSP_RESPID_itOCSP_RESPID_newOCSP_RESPONSE_freeOCSP_RESPONSE_itOCSP_RESPONSE_newOCSP_RESPONSE_printOCSP_REVOKEDINFO_freeOCSP_REVOKEDINFO_itOCSP_REVOKEDINFO_newOCSP_SERVICELOC_freeOCSP_SERVICELOC_itOCSP_SERVICELOC_newOCSP_SIGNATURE_freeOCSP_SIGNATURE_itOCSP_SIGNATURE_newOCSP_SINGLERESP_add1_ext_i2dOCSP_SINGLERESP_add_extOCSP_SINGLERESP_delete_extOCSP_SINGLERESP_freeOCSP_SINGLERESP_get1_ext_d2iOCSP_SINGLERESP_get_extOCSP_SINGLERESP_get_ext_by_NIDOCSP_SINGLERESP_get_ext_by_OBJOCSP_SINGLERESP_get_ext_by_criticalOCSP_SINGLERESP_get_ext_countOCSP_SINGLERESP_itOCSP_SINGLERESP_newOCSP_accept_responses_newOCSP_archive_cutoff_newOCSP_basic_add1_certOCSP_basic_add1_nonceOCSP_basic_add1_statusOCSP_basic_signOCSP_basic_verifyOCSP_cert_id_newOCSP_cert_status_strOCSP_cert_to_idOCSP_check_nonceOCSP_check_validityOCSP_copy_nonceOCSP_crlID_newOCSP_crl_reason_strOCSP_id_cmpOCSP_id_get0_infoOCSP_id_issuer_cmpOCSP_onereq_get0_idOCSP_parse_urlOCSP_request_add0_idOCSP_request_add1_certOCSP_request_add1_nonceOCSP_request_is_signedOCSP_request_onereq_countOCSP_request_onereq_get0OCSP_request_set1_nameOCSP_request_signOCSP_request_verifyOCSP_resp_countOCSP_resp_findOCSP_resp_find_statusOCSP_resp_get0OCSP_response_createOCSP_response_get1_basicOCSP_response_statusOCSP_response_status_strOCSP_sendreq_bioOCSP_sendreq_nbioOCSP_sendreq_newOCSP_single_get0_statusOCSP_url_svcloc_newOPENSSL_DIR_endOPENSSL_DIR_readOPENSSL_add_all_algorithms_confOPENSSL_add_all_algorithms_noconfOPENSSL_asc2uniOPENSSL_cleanseOPENSSL_configOPENSSL_cpuid_setupOPENSSL_gmtimeOPENSSL_gmtime_adjOPENSSL_ia32cap_locOPENSSL_initOPENSSL_isserviceOPENSSL_issetugidOPENSSL_load_builtin_modulesOPENSSL_memcmpOPENSSL_no_configOPENSSL_showfatalOPENSSL_stderrOPENSSL_strcasecmpOPENSSL_strncasecmpOPENSSL_uni2ascOSSL_DES_versionOSSL_libdes_versionOTHERNAME_cmpOTHERNAME_freeOTHERNAME_itOTHERNAME_newOpenSSLDieOpenSSL_add_all_ciphersOpenSSL_add_all_digestsPBE2PARAM_freePBE2PARAM_itPBE2PARAM_newPBEPARAM_freePBEPARAM_itPBEPARAM_newPBKDF2PARAM_freePBKDF2PARAM_itPBKDF2PARAM_newPEM_ASN1_readPEM_ASN1_read_bioPEM_ASN1_writePEM_ASN1_write_bioPEM_SealFinalPEM_SealInitPEM_SealUpdatePEM_SignFinalPEM_SignInitPEM_SignUpdatePEM_X509_INFO_readPEM_X509_INFO_read_bioPEM_X509_INFO_write_bioPEM_bytes_read_bioPEM_def_callbackPEM_dek_infoPEM_do_headerPEM_get_EVP_CIPHER_INFOPEM_proc_typePEM_readPEM_read_CMSPEM_read_DHparamsPEM_read_DSAPrivateKeyPEM_read_DSA_PUBKEYPEM_read_DSAparamsPEM_read_ECPKParametersPEM_read_ECPrivateKeyPEM_read_EC_PUBKEYPEM_read_NETSCAPE_CERT_SEQUENCEPEM_read_PKCS7PEM_read_PKCS8PEM_read_PKCS8_PRIV_KEY_INFOPEM_read_PUBKEYPEM_read_PrivateKeyPEM_read_RSAPrivateKeyPEM_read_RSAPublicKeyPEM_read_RSA_PUBKEYPEM_read_X509PEM_read_X509_AUXPEM_read_X509_CERT_PAIRPEM_read_X509_CRLPEM_read_X509_REQPEM_read_bioPEM_read_bio_CMSPEM_read_bio_DHparamsPEM_read_bio_DSAPrivateKeyPEM_read_bio_DSA_PUBKEYPEM_read_bio_DSAparamsPEM_read_bio_ECPKParametersPEM_read_bio_ECPrivateKeyPEM_read_bio_EC_PUBKEYPEM_read_bio_NETSCAPE_CERT_SEQUENCEPEM_read_bio_PKCS7PEM_read_bio_PKCS8PEM_read_bio_PKCS8_PRIV_KEY_INFOPEM_read_bio_PUBKEYPEM_read_bio_ParametersPEM_read_bio_PrivateKeyPEM_read_bio_RSAPrivateKeyPEM_read_bio_RSAPublicKeyPEM_read_bio_RSA_PUBKEYPEM_read_bio_X509PEM_read_bio_X509_AUXPEM_read_bio_X509_CERT_PAIRPEM_read_bio_X509_CRLPEM_read_bio_X509_REQPEM_writePEM_write_CMSPEM_write_DHparamsPEM_write_DSAPrivateKeyPEM_write_DSA_PUBKEYPEM_write_DSAparamsPEM_write_ECPKParametersPEM_write_ECPrivateKeyPEM_write_EC_PUBKEYPEM_write_NETSCAPE_CERT_SEQUENCEPEM_write_PKCS7PEM_write_PKCS8PEM_write_PKCS8PrivateKeyPEM_write_PKCS8PrivateKey_nidPEM_write_PKCS8_PRIV_KEY_INFOPEM_write_PUBKEYPEM_write_PrivateKeyPEM_write_RSAPrivateKeyPEM_write_RSAPublicKeyPEM_write_RSA_PUBKEYPEM_write_X509PEM_write_X509_AUXPEM_write_X509_CERT_PAIRPEM_write_X509_CRLPEM_write_X509_REQPEM_write_X509_REQ_NEWPEM_write_bioPEM_write_bio_ASN1_streamPEM_write_bio_CMSPEM_write_bio_CMS_streamPEM_write_bio_DHparamsPEM_write_bio_DSAPrivateKeyPEM_write_bio_DSA_PUBKEYPEM_write_bio_DSAparamsPEM_write_bio_ECPKParametersPEM_write_bio_ECPrivateKeyPEM_write_bio_EC_PUBKEYPEM_write_bio_NETSCAPE_CERT_SEQUENCEPEM_write_bio_PKCS7PEM_write_bio_PKCS7_streamPEM_write_bio_PKCS8PEM_write_bio_PKCS8PrivateKeyPEM_write_bio_PKCS8PrivateKey_nidPEM_write_bio_PKCS8_PRIV_KEY_INFOPEM_write_bio_PUBKEYPEM_write_bio_ParametersPEM_write_bio_PrivateKeyPEM_write_bio_RSAPrivateKeyPEM_write_bio_RSAPublicKeyPEM_write_bio_RSA_PUBKEYPEM_write_bio_X509PEM_write_bio_X509_AUXPEM_write_bio_X509_CERT_PAIRPEM_write_bio_X509_CRLPEM_write_bio_X509_REQPEM_write_bio_X509_REQ_NEWPKCS12_AUTHSAFES_itPKCS12_BAGS_freePKCS12_BAGS_itPKCS12_BAGS_newPKCS12_MAC_DATA_freePKCS12_MAC_DATA_itPKCS12_MAC_DATA_newPKCS12_MAKE_KEYBAGPKCS12_MAKE_SHKEYBAGPKCS12_PBE_addPKCS12_PBE_keyivgenPKCS12_SAFEBAGS_itPKCS12_SAFEBAG_freePKCS12_SAFEBAG_itPKCS12_SAFEBAG_newPKCS12_add_CSPName_ascPKCS12_add_certPKCS12_add_friendlyname_ascPKCS12_add_friendlyname_uniPKCS12_add_keyPKCS12_add_localkeyidPKCS12_add_safePKCS12_add_safesPKCS12_certbag2x509PKCS12_certbag2x509crlPKCS12_createPKCS12_decrypt_skeyPKCS12_freePKCS12_gen_macPKCS12_get_attr_genPKCS12_get_friendlynamePKCS12_initPKCS12_itPKCS12_item_decrypt_d2iPKCS12_item_i2d_encryptPKCS12_item_pack_safebagPKCS12_key_gen_ascPKCS12_key_gen_uniPKCS12_newPKCS12_newpassPKCS12_pack_authsafesPKCS12_pack_p7dataPKCS12_pack_p7encdataPKCS12_parsePKCS12_pbe_cryptPKCS12_set_macPKCS12_setup_macPKCS12_unpack_authsafesPKCS12_unpack_p7dataPKCS12_unpack_p7encdataPKCS12_verify_macPKCS12_x5092certbagPKCS12_x509crl2certbagPKCS1_MGF1PKCS5_PBE_addPKCS5_PBE_keyivgenPKCS5_PBKDF2_HMACPKCS5_PBKDF2_HMAC_SHA1PKCS5_pbe2_setPKCS5_pbe2_set_ivPKCS5_pbe_setPKCS5_pbe_set0_algorPKCS5_pbkdf2_setPKCS5_v2_PBE_keyivgenPKCS7_ATTR_SIGN_itPKCS7_ATTR_VERIFY_itPKCS7_DIGEST_freePKCS7_DIGEST_itPKCS7_DIGEST_newPKCS7_ENCRYPT_freePKCS7_ENCRYPT_itPKCS7_ENCRYPT_newPKCS7_ENC_CONTENT_freePKCS7_ENC_CONTENT_itPKCS7_ENC_CONTENT_newPKCS7_ENVELOPE_freePKCS7_ENVELOPE_itPKCS7_ENVELOPE_newPKCS7_ISSUER_AND_SERIAL_digestPKCS7_ISSUER_AND_SERIAL_freePKCS7_ISSUER_AND_SERIAL_itPKCS7_ISSUER_AND_SERIAL_newPKCS7_RECIP_INFO_freePKCS7_RECIP_INFO_get0_algPKCS7_RECIP_INFO_itPKCS7_RECIP_INFO_newPKCS7_RECIP_INFO_setPKCS7_SIGNED_freePKCS7_SIGNED_itPKCS7_SIGNED_newPKCS7_SIGNER_INFO_freePKCS7_SIGNER_INFO_get0_algsPKCS7_SIGNER_INFO_itPKCS7_SIGNER_INFO_newPKCS7_SIGNER_INFO_setPKCS7_SIGNER_INFO_signPKCS7_SIGN_ENVELOPE_freePKCS7_SIGN_ENVELOPE_itPKCS7_SIGN_ENVELOPE_newPKCS7_add0_attrib_signing_timePKCS7_add1_attrib_digestPKCS7_add_attrib_content_typePKCS7_add_attrib_smimecapPKCS7_add_attributePKCS7_add_certificatePKCS7_add_crlPKCS7_add_recipientPKCS7_add_recipient_infoPKCS7_add_signaturePKCS7_add_signed_attributePKCS7_add_signerPKCS7_cert_from_signer_infoPKCS7_content_newPKCS7_ctrlPKCS7_dataDecodePKCS7_dataFinalPKCS7_dataInitPKCS7_dataVerifyPKCS7_decryptPKCS7_digest_from_attributesPKCS7_dupPKCS7_encryptPKCS7_finalPKCS7_freePKCS7_get0_signersPKCS7_get_attributePKCS7_get_issuer_and_serialPKCS7_get_signed_attributePKCS7_get_signer_infoPKCS7_get_smimecapPKCS7_itPKCS7_newPKCS7_print_ctxPKCS7_set0_type_otherPKCS7_set_attributesPKCS7_set_cipherPKCS7_set_contentPKCS7_set_digestPKCS7_set_signed_attributesPKCS7_set_typePKCS7_signPKCS7_sign_add_signerPKCS7_signatureVerifyPKCS7_simple_smimecapPKCS7_streamPKCS7_to_TS_TST_INFOPKCS7_verifyPKCS8_PRIV_KEY_INFO_freePKCS8_PRIV_KEY_INFO_itPKCS8_PRIV_KEY_INFO_newPKCS8_add_keyusagePKCS8_decryptPKCS8_encryptPKCS8_pkey_get0PKCS8_pkey_set0PKCS8_set_brokenPKEY_USAGE_PERIOD_freePKEY_USAGE_PERIOD_itPKEY_USAGE_PERIOD_newPOLICYINFO_freePOLICYINFO_itPOLICYINFO_newPOLICYQUALINFO_freePOLICYQUALINFO_itPOLICYQUALINFO_newPOLICY_CONSTRAINTS_freePOLICY_CONSTRAINTS_itPOLICY_CONSTRAINTS_newPOLICY_MAPPINGS_itPOLICY_MAPPING_freePOLICY_MAPPING_itPOLICY_MAPPING_newPROXY_CERT_INFO_EXTENSION_freePROXY_CERT_INFO_EXTENSION_itPROXY_CERT_INFO_EXTENSION_newPROXY_POLICY_freePROXY_POLICY_itPROXY_POLICY_newRAND_SSLeayRAND_addRAND_bytesRAND_cleanupRAND_egdRAND_egd_bytesRAND_eventRAND_file_nameRAND_get_rand_methodRAND_load_fileRAND_pollRAND_pseudo_bytesRAND_query_egd_bytesRAND_screenRAND_seedRAND_set_rand_engineRAND_set_rand_methodRAND_statusRAND_write_fileRC2_cbc_encryptRC2_cfb64_encryptRC2_decryptRC2_ecb_encryptRC2_encryptRC2_ofb64_encryptRC2_set_keyRC4RC4_optionsRC4_set_keyRIPEMD160RIPEMD160_FinalRIPEMD160_InitRIPEMD160_TransformRIPEMD160_UpdateRSAPrivateKey_dupRSAPrivateKey_itRSAPublicKey_dupRSAPublicKey_itRSA_PKCS1_SSLeayRSA_PSS_PARAMS_freeRSA_PSS_PARAMS_itRSA_PSS_PARAMS_newRSA_X931_hash_idRSA_blinding_offRSA_blinding_onRSA_check_keyRSA_flagsRSA_freeRSA_generate_keyRSA_generate_key_exRSA_get_default_methodRSA_get_ex_dataRSA_get_ex_new_indexRSA_get_methodRSA_memory_lockRSA_newRSA_new_methodRSA_null_methodRSA_padding_add_PKCS1_OAEPRSA_padding_add_PKCS1_PSSRSA_padding_add_PKCS1_PSS_mgf1RSA_padding_add_PKCS1_type_1RSA_padding_add_PKCS1_type_2RSA_padding_add_SSLv23RSA_padding_add_X931RSA_padding_add_noneRSA_padding_check_PKCS1_OAEPRSA_padding_check_PKCS1_type_1RSA_padding_check_PKCS1_type_2RSA_padding_check_SSLv23RSA_padding_check_X931RSA_padding_check_noneRSA_printRSA_print_fpRSA_private_decryptRSA_private_encryptRSA_public_decryptRSA_public_encryptRSA_set_default_methodRSA_set_ex_dataRSA_set_methodRSA_setup_blindingRSA_signRSA_sign_ASN1_OCTET_STRINGRSA_sizeRSA_up_refRSA_verifyRSA_verify_ASN1_OCTET_STRINGRSA_verify_PKCS1_PSSRSA_verify_PKCS1_PSS_mgf1SEED_cbc_encryptSEED_cfb128_encryptSEED_decryptSEED_ecb_encryptSEED_encryptSEED_ofb128_encryptSEED_set_keySHASHA1SHA1_FinalSHA1_InitSHA1_TransformSHA1_UpdateSHA224SHA224_FinalSHA224_InitSHA224_UpdateSHA256SHA256_FinalSHA256_InitSHA256_TransformSHA256_UpdateSHA384SHA384_FinalSHA384_InitSHA384_UpdateSHA512SHA512_FinalSHA512_InitSHA512_TransformSHA512_UpdateSHA_FinalSHA_InitSHA_TransformSHA_UpdateSMIME_crlf_copySMIME_read_ASN1SMIME_read_CMSSMIME_read_PKCS7SMIME_textSMIME_write_ASN1SMIME_write_CMSSMIME_write_PKCS7SRP_Calc_ASRP_Calc_BSRP_Calc_client_keySRP_Calc_server_keySRP_Calc_uSRP_Calc_xSRP_VBASE_freeSRP_VBASE_get_by_userSRP_VBASE_initSRP_VBASE_newSRP_Verify_A_mod_NSRP_Verify_B_mod_NSRP_check_known_gN_paramSRP_create_verifierSRP_create_verifier_BNSRP_get_default_gNSSLeaySSLeay_versionSXNETID_freeSXNETID_itSXNETID_newSXNET_add_id_INTEGERSXNET_add_id_ascSXNET_add_id_ulongSXNET_freeSXNET_get_id_INTEGERSXNET_get_id_ascSXNET_get_id_ulongSXNET_itSXNET_newTS_ACCURACY_dupTS_ACCURACY_freeTS_ACCURACY_get_microsTS_ACCURACY_get_millisTS_ACCURACY_get_secondsTS_ACCURACY_newTS_ACCURACY_set_microsTS_ACCURACY_set_millisTS_ACCURACY_set_secondsTS_ASN1_INTEGER_print_bioTS_CONF_get_tsa_sectionTS_CONF_load_certTS_CONF_load_certsTS_CONF_load_keyTS_CONF_set_accuracyTS_CONF_set_certsTS_CONF_set_clock_precision_digitsTS_CONF_set_crypto_deviceTS_CONF_set_def_policyTS_CONF_set_default_engineTS_CONF_set_digestsTS_CONF_set_ess_cert_id_chainTS_CONF_set_orderingTS_CONF_set_policiesTS_CONF_set_serialTS_CONF_set_signer_certTS_CONF_set_signer_keyTS_CONF_set_tsa_nameTS_MSG_IMPRINT_dupTS_MSG_IMPRINT_freeTS_MSG_IMPRINT_get_algoTS_MSG_IMPRINT_get_msgTS_MSG_IMPRINT_newTS_MSG_IMPRINT_print_bioTS_MSG_IMPRINT_set_algoTS_MSG_IMPRINT_set_msgTS_OBJ_print_bioTS_REQ_add_extTS_REQ_delete_extTS_REQ_dupTS_REQ_ext_freeTS_REQ_freeTS_REQ_get_cert_reqTS_REQ_get_extTS_REQ_get_ext_by_NIDTS_REQ_get_ext_by_OBJTS_REQ_get_ext_by_criticalTS_REQ_get_ext_countTS_REQ_get_ext_d2iTS_REQ_get_extsTS_REQ_get_msg_imprintTS_REQ_get_nonceTS_REQ_get_policy_idTS_REQ_get_versionTS_REQ_newTS_REQ_print_bioTS_REQ_set_cert_reqTS_REQ_set_msg_imprintTS_REQ_set_nonceTS_REQ_set_policy_idTS_REQ_set_versionTS_REQ_to_TS_VERIFY_CTXTS_RESP_CTX_add_failure_infoTS_RESP_CTX_add_flagsTS_RESP_CTX_add_mdTS_RESP_CTX_add_policyTS_RESP_CTX_freeTS_RESP_CTX_get_requestTS_RESP_CTX_get_tst_infoTS_RESP_CTX_newTS_RESP_CTX_set_accuracyTS_RESP_CTX_set_certsTS_RESP_CTX_set_clock_precision_digitsTS_RESP_CTX_set_def_policyTS_RESP_CTX_set_extension_cbTS_RESP_CTX_set_serial_cbTS_RESP_CTX_set_signer_certTS_RESP_CTX_set_signer_keyTS_RESP_CTX_set_status_infoTS_RESP_CTX_set_status_info_condTS_RESP_CTX_set_time_cbTS_RESP_create_responseTS_RESP_dupTS_RESP_freeTS_RESP_get_status_infoTS_RESP_get_tokenTS_RESP_get_tst_infoTS_RESP_newTS_RESP_print_bioTS_RESP_set_status_infoTS_RESP_set_tst_infoTS_RESP_verify_responseTS_RESP_verify_signatureTS_RESP_verify_tokenTS_STATUS_INFO_dupTS_STATUS_INFO_freeTS_STATUS_INFO_newTS_STATUS_INFO_print_bioTS_TST_INFO_add_extTS_TST_INFO_delete_extTS_TST_INFO_dupTS_TST_INFO_ext_freeTS_TST_INFO_freeTS_TST_INFO_get_accuracyTS_TST_INFO_get_extTS_TST_INFO_get_ext_by_NIDTS_TST_INFO_get_ext_by_OBJTS_TST_INFO_get_ext_by_criticalTS_TST_INFO_get_ext_countTS_TST_INFO_get_ext_d2iTS_TST_INFO_get_extsTS_TST_INFO_get_msg_imprintTS_TST_INFO_get_nonceTS_TST_INFO_get_orderingTS_TST_INFO_get_policy_idTS_TST_INFO_get_serialTS_TST_INFO_get_timeTS_TST_INFO_get_tsaTS_TST_INFO_get_versionTS_TST_INFO_newTS_TST_INFO_print_bioTS_TST_INFO_set_accuracyTS_TST_INFO_set_msg_imprintTS_TST_INFO_set_nonceTS_TST_INFO_set_orderingTS_TST_INFO_set_policy_idTS_TST_INFO_set_serialTS_TST_INFO_set_timeTS_TST_INFO_set_tsaTS_TST_INFO_set_versionTS_VERIFY_CTX_cleanupTS_VERIFY_CTX_freeTS_VERIFY_CTX_initTS_VERIFY_CTX_newTS_X509_ALGOR_print_bioTS_ext_print_bioTXT_DB_create_indexTXT_DB_freeTXT_DB_get_by_indexTXT_DB_insertTXT_DB_readTXT_DB_writeUI_OpenSSLUI_UTIL_read_pwUI_UTIL_read_pw_stringUI_add_error_stringUI_add_info_stringUI_add_input_booleanUI_add_input_stringUI_add_user_dataUI_add_verify_stringUI_construct_promptUI_create_methodUI_ctrlUI_destroy_methodUI_dup_error_stringUI_dup_info_stringUI_dup_input_booleanUI_dup_input_stringUI_dup_verify_stringUI_freeUI_get0_action_stringUI_get0_output_stringUI_get0_resultUI_get0_result_stringUI_get0_test_stringUI_get0_user_dataUI_get_default_methodUI_get_ex_dataUI_get_ex_new_indexUI_get_input_flagsUI_get_methodUI_get_result_maxsizeUI_get_result_minsizeUI_get_string_typeUI_method_get_closerUI_method_get_flusherUI_method_get_openerUI_method_get_prompt_constructorUI_method_get_readerUI_method_get_writerUI_method_set_closerUI_method_set_flusherUI_method_set_openerUI_method_set_prompt_constructorUI_method_set_readerUI_method_set_writerUI_newUI_new_methodUI_processUI_set_default_methodUI_set_ex_dataUI_set_methodUI_set_resultUSERNOTICE_freeUSERNOTICE_itUSERNOTICE_newUTF8_getcUTF8_putcWHIRLPOOLWHIRLPOOL_BitUpdateWHIRLPOOL_FinalWHIRLPOOL_InitWHIRLPOOL_UpdateX509V3_EXT_CRL_add_confX509V3_EXT_CRL_add_nconfX509V3_EXT_REQ_add_confX509V3_EXT_REQ_add_nconfX509V3_EXT_addX509V3_EXT_add_aliasX509V3_EXT_add_confX509V3_EXT_add_listX509V3_EXT_add_nconfX509V3_EXT_add_nconf_skX509V3_EXT_cleanupX509V3_EXT_confX509V3_EXT_conf_nidX509V3_EXT_d2iX509V3_EXT_getX509V3_EXT_get_nidX509V3_EXT_i2dX509V3_EXT_nconfX509V3_EXT_nconf_nidX509V3_EXT_printX509V3_EXT_print_fpX509V3_EXT_val_prnX509V3_NAME_from_sectionX509V3_add1_i2dX509V3_add_standard_extensionsX509V3_add_valueX509V3_add_value_boolX509V3_add_value_bool_nfX509V3_add_value_intX509V3_add_value_ucharX509V3_conf_freeX509V3_extensions_printX509V3_get_d2iX509V3_get_sectionX509V3_get_stringX509V3_get_value_boolX509V3_get_value_intX509V3_parse_listX509V3_section_freeX509V3_set_conf_lhashX509V3_set_ctxX509V3_set_nconfX509V3_string_freeX509_ALGORS_itX509_ALGOR_dupX509_ALGOR_freeX509_ALGOR_get0X509_ALGOR_itX509_ALGOR_newX509_ALGOR_set0X509_ALGOR_set_mdX509_ATTRIBUTE_countX509_ATTRIBUTE_createX509_ATTRIBUTE_create_by_NIDX509_ATTRIBUTE_create_by_OBJX509_ATTRIBUTE_create_by_txtX509_ATTRIBUTE_dupX509_ATTRIBUTE_freeX509_ATTRIBUTE_get0_dataX509_ATTRIBUTE_get0_objectX509_ATTRIBUTE_get0_typeX509_ATTRIBUTE_itX509_ATTRIBUTE_newX509_ATTRIBUTE_set1_dataX509_ATTRIBUTE_set1_objectX509_CERT_AUX_freeX509_CERT_AUX_itX509_CERT_AUX_newX509_CERT_AUX_printX509_CERT_PAIR_freeX509_CERT_PAIR_itX509_CERT_PAIR_newX509_CINF_freeX509_CINF_itX509_CINF_newX509_CRL_INFO_freeX509_CRL_INFO_itX509_CRL_INFO_newX509_CRL_METHOD_freeX509_CRL_METHOD_newX509_CRL_add0_revokedX509_CRL_add1_ext_i2dX509_CRL_add_extX509_CRL_cmpX509_CRL_delete_extX509_CRL_digestX509_CRL_dupX509_CRL_freeX509_CRL_get0_by_certX509_CRL_get0_by_serialX509_CRL_get_extX509_CRL_get_ext_by_NIDX509_CRL_get_ext_by_OBJX509_CRL_get_ext_by_criticalX509_CRL_get_ext_countX509_CRL_get_ext_d2iX509_CRL_get_meth_dataX509_CRL_itX509_CRL_matchX509_CRL_newX509_CRL_printX509_CRL_print_fpX509_CRL_set_default_methodX509_CRL_set_issuer_nameX509_CRL_set_lastUpdateX509_CRL_set_meth_dataX509_CRL_set_nextUpdateX509_CRL_set_versionX509_CRL_signX509_CRL_sign_ctxX509_CRL_sortX509_CRL_verifyX509_EXTENSIONS_itX509_EXTENSION_create_by_NIDX509_EXTENSION_create_by_OBJX509_EXTENSION_dupX509_EXTENSION_freeX509_EXTENSION_get_criticalX509_EXTENSION_get_dataX509_EXTENSION_get_objectX509_EXTENSION_itX509_EXTENSION_newX509_EXTENSION_set_criticalX509_EXTENSION_set_dataX509_EXTENSION_set_objectX509_INFO_freeX509_INFO_newX509_LOOKUP_by_aliasX509_LOOKUP_by_fingerprintX509_LOOKUP_by_issuer_serialX509_LOOKUP_by_subjectX509_LOOKUP_ctrlX509_LOOKUP_fileX509_LOOKUP_freeX509_LOOKUP_hash_dirX509_LOOKUP_initX509_LOOKUP_newX509_LOOKUP_shutdownX509_NAME_ENTRY_create_by_NIDX509_NAME_ENTRY_create_by_OBJX509_NAME_ENTRY_create_by_txtX509_NAME_ENTRY_dupX509_NAME_ENTRY_freeX509_NAME_ENTRY_get_dataX509_NAME_ENTRY_get_objectX509_NAME_ENTRY_itX509_NAME_ENTRY_newX509_NAME_ENTRY_set_dataX509_NAME_ENTRY_set_objectX509_NAME_add_entryX509_NAME_add_entry_by_NIDX509_NAME_add_entry_by_OBJX509_NAME_add_entry_by_txtX509_NAME_cmpX509_NAME_delete_entryX509_NAME_digestX509_NAME_dupX509_NAME_entry_countX509_NAME_freeX509_NAME_get_entryX509_NAME_get_index_by_NIDX509_NAME_get_index_by_OBJX509_NAME_get_text_by_NIDX509_NAME_get_text_by_OBJX509_NAME_hashX509_NAME_hash_oldX509_NAME_itX509_NAME_newX509_NAME_onelineX509_NAME_printX509_NAME_print_exX509_NAME_print_ex_fpX509_NAME_setX509_OBJECT_free_contentsX509_OBJECT_idx_by_subjectX509_OBJECT_retrieve_by_subjectX509_OBJECT_retrieve_matchX509_OBJECT_up_ref_countX509_PKEY_freeX509_PKEY_newX509_POLICY_NODE_printX509_PUBKEY_freeX509_PUBKEY_getX509_PUBKEY_get0_paramX509_PUBKEY_itX509_PUBKEY_newX509_PUBKEY_setX509_PUBKEY_set0_paramX509_PURPOSE_addX509_PURPOSE_cleanupX509_PURPOSE_get0X509_PURPOSE_get0_nameX509_PURPOSE_get0_snameX509_PURPOSE_get_by_idX509_PURPOSE_get_by_snameX509_PURPOSE_get_countX509_PURPOSE_get_idX509_PURPOSE_get_trustX509_PURPOSE_setX509_REQ_INFO_freeX509_REQ_INFO_itX509_REQ_INFO_newX509_REQ_add1_attrX509_REQ_add1_attr_by_NIDX509_REQ_add1_attr_by_OBJX509_REQ_add1_attr_by_txtX509_REQ_add_extensionsX509_REQ_add_extensions_nidX509_REQ_check_private_keyX509_REQ_delete_attrX509_REQ_digestX509_REQ_dupX509_REQ_extension_nidX509_REQ_freeX509_REQ_get1_emailX509_REQ_get_attrX509_REQ_get_attr_by_NIDX509_REQ_get_attr_by_OBJX509_REQ_get_attr_countX509_REQ_get_extension_nidsX509_REQ_get_extensionsX509_REQ_get_pubkeyX509_REQ_itX509_REQ_newX509_REQ_printX509_REQ_print_exX509_REQ_print_fpX509_REQ_set_extension_nidsX509_REQ_set_pubkeyX509_REQ_set_subject_nameX509_REQ_set_versionX509_REQ_signX509_REQ_sign_ctxX509_REQ_to_X509X509_REQ_verifyX509_REVOKED_add1_ext_i2dX509_REVOKED_add_extX509_REVOKED_delete_extX509_REVOKED_freeX509_REVOKED_get_extX509_REVOKED_get_ext_by_NIDX509_REVOKED_get_ext_by_OBJX509_REVOKED_get_ext_by_criticalX509_REVOKED_get_ext_countX509_REVOKED_get_ext_d2iX509_REVOKED_itX509_REVOKED_newX509_REVOKED_set_revocationDateX509_REVOKED_set_serialNumberX509_SIG_freeX509_SIG_itX509_SIG_newX509_STORE_CTX_cleanupX509_STORE_CTX_freeX509_STORE_CTX_get0_current_crlX509_STORE_CTX_get0_current_issuerX509_STORE_CTX_get0_paramX509_STORE_CTX_get0_parent_ctxX509_STORE_CTX_get0_policy_treeX509_STORE_CTX_get1_chainX509_STORE_CTX_get1_issuerX509_STORE_CTX_get_chainX509_STORE_CTX_get_current_certX509_STORE_CTX_get_errorX509_STORE_CTX_get_error_depthX509_STORE_CTX_get_ex_dataX509_STORE_CTX_get_ex_new_indexX509_STORE_CTX_get_explicit_policyX509_STORE_CTX_initX509_STORE_CTX_newX509_STORE_CTX_purpose_inheritX509_STORE_CTX_set0_crlsX509_STORE_CTX_set0_paramX509_STORE_CTX_set_certX509_STORE_CTX_set_chainX509_STORE_CTX_set_defaultX509_STORE_CTX_set_depthX509_STORE_CTX_set_errorX509_STORE_CTX_set_ex_dataX509_STORE_CTX_set_flagsX509_STORE_CTX_set_purposeX509_STORE_CTX_set_timeX509_STORE_CTX_set_trustX509_STORE_CTX_set_verify_cbX509_STORE_CTX_trusted_stackX509_STORE_add_certX509_STORE_add_crlX509_STORE_add_lookupX509_STORE_freeX509_STORE_get1_certsX509_STORE_get1_crlsX509_STORE_get_by_subjectX509_STORE_load_locationsX509_STORE_newX509_STORE_set1_paramX509_STORE_set_default_pathsX509_STORE_set_depthX509_STORE_set_flagsX509_STORE_set_purposeX509_STORE_set_trustX509_STORE_set_verify_cbX509_TRUST_addX509_TRUST_cleanupX509_TRUST_get0X509_TRUST_get0_nameX509_TRUST_get_by_idX509_TRUST_get_countX509_TRUST_get_flagsX509_TRUST_get_trustX509_TRUST_setX509_TRUST_set_defaultX509_VAL_freeX509_VAL_itX509_VAL_newX509_VERIFY_PARAM_add0_policyX509_VERIFY_PARAM_add0_tableX509_VERIFY_PARAM_clear_flagsX509_VERIFY_PARAM_freeX509_VERIFY_PARAM_get_depthX509_VERIFY_PARAM_get_flagsX509_VERIFY_PARAM_inheritX509_VERIFY_PARAM_lookupX509_VERIFY_PARAM_newX509_VERIFY_PARAM_set1X509_VERIFY_PARAM_set1_nameX509_VERIFY_PARAM_set1_policiesX509_VERIFY_PARAM_set_depthX509_VERIFY_PARAM_set_flagsX509_VERIFY_PARAM_set_purposeX509_VERIFY_PARAM_set_timeX509_VERIFY_PARAM_set_trustX509_VERIFY_PARAM_table_cleanupX509_add1_ext_i2dX509_add1_reject_objectX509_add1_trust_objectX509_add_extX509_alias_get0X509_alias_set1X509_certificate_typeX509_check_akidX509_check_caX509_check_issuedX509_check_private_keyX509_check_purposeX509_check_trustX509_cmpX509_cmp_current_timeX509_cmp_timeX509_delete_extX509_digestX509_dupX509_email_freeX509_find_by_issuer_and_serialX509_find_by_subjectX509_freeX509_get0_pubkey_bitstrX509_get1_emailX509_get1_ocspX509_get_default_cert_areaX509_get_default_cert_dirX509_get_default_cert_dir_envX509_get_default_cert_fileX509_get_default_cert_file_envX509_get_default_private_dirX509_get_ex_dataX509_get_ex_new_indexX509_get_extX509_get_ext_by_NIDX509_get_ext_by_OBJX509_get_ext_by_criticalX509_get_ext_countX509_get_ext_d2iX509_get_issuer_nameX509_get_pubkeyX509_get_pubkey_parametersX509_get_serialNumberX509_get_subject_nameX509_gmtime_adjX509_issuer_and_serial_cmpX509_issuer_and_serial_hashX509_issuer_name_cmpX509_issuer_name_hashX509_issuer_name_hash_oldX509_itX509_keyid_get0X509_keyid_set1X509_load_cert_crl_fileX509_load_cert_fileX509_load_crl_fileX509_newX509_ocspid_printX509_policy_checkX509_policy_level_get0_nodeX509_policy_level_node_countX509_policy_node_get0_parentX509_policy_node_get0_policyX509_policy_node_get0_qualifiersX509_policy_tree_freeX509_policy_tree_get0_levelX509_policy_tree_get0_policiesX509_policy_tree_get0_user_policiesX509_policy_tree_level_countX509_printX509_print_exX509_print_ex_fpX509_print_fpX509_pubkey_digestX509_reject_clearX509_set_ex_dataX509_set_issuer_nameX509_set_notAfterX509_set_notBeforeX509_set_pubkeyX509_set_serialNumberX509_set_subject_nameX509_set_versionX509_signX509_sign_ctxX509_signature_dumpX509_signature_printX509_subject_name_cmpX509_subject_name_hashX509_subject_name_hash_oldX509_supported_extensionX509_time_adjX509_time_adj_exX509_to_X509_REQX509_trust_clearX509_verifyX509_verify_certX509_verify_cert_error_stringX509at_add1_attrX509at_add1_attr_by_NIDX509at_add1_attr_by_OBJX509at_add1_attr_by_txtX509at_delete_attrX509at_get0_data_by_OBJX509at_get_attrX509at_get_attr_by_NIDX509at_get_attr_by_OBJX509at_get_attr_countX509v3_add_extX509v3_delete_extX509v3_get_extX509v3_get_ext_by_NIDX509v3_get_ext_by_OBJX509v3_get_ext_by_criticalX509v3_get_ext_countZLONG_it_ossl_096_des_random_seed_ossl_old_crypt_ossl_old_des_cbc_cksum_ossl_old_des_cbc_encrypt_ossl_old_des_cfb64_encrypt_ossl_old_des_cfb_encrypt_ossl_old_des_crypt_ossl_old_des_decrypt3_ossl_old_des_ecb3_encrypt_ossl_old_des_ecb_encrypt_ossl_old_des_ede3_cbc_encrypt_ossl_old_des_ede3_cfb64_encrypt_ossl_old_des_ede3_ofb64_encrypt_ossl_old_des_enc_read_ossl_old_des_enc_write_ossl_old_des_encrypt_ossl_old_des_encrypt2_ossl_old_des_encrypt3_ossl_old_des_fcrypt_ossl_old_des_is_weak_key_ossl_old_des_key_sched_ossl_old_des_ncbc_encrypt_ossl_old_des_ofb64_encrypt_ossl_old_des_ofb_encrypt_ossl_old_des_options_ossl_old_des_pcbc_encrypt_ossl_old_des_quad_cksum_ossl_old_des_random_key_ossl_old_des_random_seed_ossl_old_des_read_2passwords_ossl_old_des_read_password_ossl_old_des_read_pw_ossl_old_des_read_pw_string_ossl_old_des_set_key_ossl_old_des_set_odd_parity_ossl_old_des_string_to_2keys_ossl_old_des_string_to_key_ossl_old_des_xcbc_encrypt_shadow_DES_check_key_shadow_DES_rw_modea2d_ASN1_OBJECTa2i_ASN1_ENUMERATEDa2i_ASN1_INTEGERa2i_ASN1_STRINGa2i_GENERAL_NAMEa2i_IPADDRESSa2i_IPADDRESS_NCa2i_ipaddasn1_Finishasn1_GetSequenceasn1_add_errorasn1_const_Finishasn1_do_adbasn1_do_lockasn1_enc_freeasn1_enc_initasn1_enc_restoreasn1_enc_saveasn1_ex_c2iasn1_ex_i2casn1_get_choice_selectorasn1_get_field_ptrasn1_set_choice_selectorb2i_PVK_biob2i_PrivateKeyb2i_PrivateKey_biob2i_PublicKeyb2i_PublicKey_biobn_add_wordsbn_div_wordsbn_dup_expandbn_expand2bn_mul_add_wordsbn_mul_wordsbn_sqr_wordsbn_sub_wordsc2i_ASN1_BIT_STRINGc2i_ASN1_INTEGERc2i_ASN1_OBJECTcheck_deferd2i_ACCESS_DESCRIPTIONd2i_ASN1_BIT_STRINGd2i_ASN1_BMPSTRINGd2i_ASN1_BOOLEANd2i_ASN1_ENUMERATEDd2i_ASN1_GENERALIZEDTIMEd2i_ASN1_GENERALSTRINGd2i_ASN1_IA5STRINGd2i_ASN1_INTEGERd2i_ASN1_NULLd2i_ASN1_OBJECTd2i_ASN1_OCTET_STRINGd2i_ASN1_PRINTABLEd2i_ASN1_PRINTABLESTRINGd2i_ASN1_SEQUENCE_ANYd2i_ASN1_SETd2i_ASN1_SET_ANYd2i_ASN1_T61STRINGd2i_ASN1_TIMEd2i_ASN1_TYPEd2i_ASN1_UINTEGERd2i_ASN1_UNIVERSALSTRINGd2i_ASN1_UTCTIMEd2i_ASN1_UTF8STRINGd2i_ASN1_VISIBLESTRINGd2i_ASN1_bytesd2i_ASN1_type_bytesd2i_AUTHORITY_INFO_ACCESSd2i_AUTHORITY_KEYIDd2i_AutoPrivateKeyd2i_BASIC_CONSTRAINTSd2i_CERTIFICATEPOLICIESd2i_CMS_ContentInfod2i_CMS_ReceiptRequestd2i_CMS_biod2i_CRL_DIST_POINTSd2i_DHparamsd2i_DIRECTORYSTRINGd2i_DISPLAYTEXTd2i_DIST_POINTd2i_DIST_POINT_NAMEd2i_DSAPrivateKeyd2i_DSAPrivateKey_biod2i_DSAPrivateKey_fpd2i_DSAPublicKeyd2i_DSA_PUBKEYd2i_DSA_PUBKEY_biod2i_DSA_PUBKEY_fpd2i_DSA_SIGd2i_DSAparamsd2i_ECDSA_SIGd2i_ECPKParametersd2i_ECParametersd2i_ECPrivateKeyd2i_ECPrivateKey_biod2i_ECPrivateKey_fpd2i_EC_PUBKEYd2i_EC_PUBKEY_biod2i_EC_PUBKEY_fpd2i_EDIPARTYNAMEd2i_ESS_CERT_IDd2i_ESS_ISSUER_SERIALd2i_ESS_SIGNING_CERTd2i_EXTENDED_KEY_USAGEd2i_GENERAL_NAMEd2i_GENERAL_NAMESd2i_ISSUING_DIST_POINTd2i_KRB5_APREQd2i_KRB5_APREQBODYd2i_KRB5_AUTHDATAd2i_KRB5_AUTHENTd2i_KRB5_AUTHENTBODYd2i_KRB5_CHECKSUMd2i_KRB5_ENCDATAd2i_KRB5_ENCKEYd2i_KRB5_PRINCNAMEd2i_KRB5_TICKETd2i_KRB5_TKTBODYd2i_NETSCAPE_CERT_SEQUENCEd2i_NETSCAPE_SPKACd2i_NETSCAPE_SPKId2i_NETSCAPE_X509d2i_NOTICEREFd2i_Netscape_RSAd2i_OCSP_BASICRESPd2i_OCSP_CERTIDd2i_OCSP_CERTSTATUSd2i_OCSP_CRLIDd2i_OCSP_ONEREQd2i_OCSP_REQINFOd2i_OCSP_REQUESTd2i_OCSP_RESPBYTESd2i_OCSP_RESPDATAd2i_OCSP_RESPIDd2i_OCSP_RESPONSEd2i_OCSP_REVOKEDINFOd2i_OCSP_SERVICELOCd2i_OCSP_SIGNATUREd2i_OCSP_SINGLERESPd2i_OTHERNAMEd2i_PBE2PARAMd2i_PBEPARAMd2i_PBKDF2PARAMd2i_PKCS12d2i_PKCS12_BAGSd2i_PKCS12_MAC_DATAd2i_PKCS12_SAFEBAGd2i_PKCS12_biod2i_PKCS12_fpd2i_PKCS7d2i_PKCS7_DIGESTd2i_PKCS7_ENCRYPTd2i_PKCS7_ENC_CONTENTd2i_PKCS7_ENVELOPEd2i_PKCS7_ISSUER_AND_SERIALd2i_PKCS7_RECIP_INFOd2i_PKCS7_SIGNEDd2i_PKCS7_SIGNER_INFOd2i_PKCS7_SIGN_ENVELOPEd2i_PKCS7_biod2i_PKCS7_fpd2i_PKCS8PrivateKey_biod2i_PKCS8PrivateKey_fpd2i_PKCS8_PRIV_KEY_INFOd2i_PKCS8_PRIV_KEY_INFO_biod2i_PKCS8_PRIV_KEY_INFO_fpd2i_PKCS8_biod2i_PKCS8_fpd2i_PKEY_USAGE_PERIODd2i_POLICYINFOd2i_POLICYQUALINFOd2i_PROXY_CERT_INFO_EXTENSIONd2i_PROXY_POLICYd2i_PUBKEYd2i_PUBKEY_biod2i_PUBKEY_fpd2i_PrivateKeyd2i_PrivateKey_biod2i_PrivateKey_fpd2i_PublicKeyd2i_RSAPrivateKeyd2i_RSAPrivateKey_biod2i_RSAPrivateKey_fpd2i_RSAPublicKeyd2i_RSAPublicKey_biod2i_RSAPublicKey_fpd2i_RSA_NETd2i_RSA_PSS_PARAMSd2i_RSA_PUBKEYd2i_RSA_PUBKEY_biod2i_RSA_PUBKEY_fpd2i_SXNETd2i_SXNETIDd2i_TS_ACCURACYd2i_TS_MSG_IMPRINTd2i_TS_MSG_IMPRINT_biod2i_TS_MSG_IMPRINT_fpd2i_TS_REQd2i_TS_REQ_biod2i_TS_REQ_fpd2i_TS_RESPd2i_TS_RESP_biod2i_TS_RESP_fpd2i_TS_STATUS_INFOd2i_TS_TST_INFOd2i_TS_TST_INFO_biod2i_TS_TST_INFO_fpd2i_USERNOTICEd2i_X509d2i_X509_ALGORd2i_X509_ALGORSd2i_X509_ATTRIBUTEd2i_X509_AUXd2i_X509_CERT_AUXd2i_X509_CERT_PAIRd2i_X509_CINFd2i_X509_CRLd2i_X509_CRL_INFOd2i_X509_CRL_biod2i_X509_CRL_fpd2i_X509_EXTENSIONd2i_X509_EXTENSIONSd2i_X509_NAMEd2i_X509_NAME_ENTRYd2i_X509_PKEYd2i_X509_PUBKEYd2i_X509_REQd2i_X509_REQ_INFOd2i_X509_REQ_biod2i_X509_REQ_fpd2i_X509_REVOKEDd2i_X509_SIGd2i_X509_VALd2i_X509_biod2i_X509_fpget_rfc2409_prime_1024get_rfc2409_prime_768get_rfc3526_prime_1536get_rfc3526_prime_2048get_rfc3526_prime_3072get_rfc3526_prime_4096get_rfc3526_prime_6144get_rfc3526_prime_8192hex_to_stringi2a_ACCESS_DESCRIPTIONi2a_ASN1_ENUMERATEDi2a_ASN1_INTEGERi2a_ASN1_OBJECTi2a_ASN1_STRINGi2b_PVK_bioi2b_PrivateKey_bioi2b_PublicKey_bioi2c_ASN1_BIT_STRINGi2c_ASN1_INTEGERi2d_ACCESS_DESCRIPTIONi2d_ASN1_BIT_STRINGi2d_ASN1_BMPSTRINGi2d_ASN1_BOOLEANi2d_ASN1_ENUMERATEDi2d_ASN1_GENERALIZEDTIMEi2d_ASN1_GENERALSTRINGi2d_ASN1_IA5STRINGi2d_ASN1_INTEGERi2d_ASN1_NULLi2d_ASN1_OBJECTi2d_ASN1_OCTET_STRINGi2d_ASN1_PRINTABLEi2d_ASN1_PRINTABLESTRINGi2d_ASN1_SEQUENCE_ANYi2d_ASN1_SETi2d_ASN1_SET_ANYi2d_ASN1_T61STRINGi2d_ASN1_TIMEi2d_ASN1_TYPEi2d_ASN1_UNIVERSALSTRINGi2d_ASN1_UTCTIMEi2d_ASN1_UTF8STRINGi2d_ASN1_VISIBLESTRINGi2d_ASN1_bio_streami2d_ASN1_bytesi2d_AUTHORITY_INFO_ACCESSi2d_AUTHORITY_KEYIDi2d_BASIC_CONSTRAINTSi2d_CERTIFICATEPOLICIESi2d_CMS_ContentInfoi2d_CMS_ReceiptRequesti2d_CMS_bioi2d_CMS_bio_streami2d_CRL_DIST_POINTSi2d_DHparamsi2d_DIRECTORYSTRINGi2d_DISPLAYTEXTi2d_DIST_POINTi2d_DIST_POINT_NAMEi2d_DSAPrivateKeyi2d_DSAPrivateKey_bioi2d_DSAPrivateKey_fpi2d_DSAPublicKeyi2d_DSA_PUBKEYi2d_DSA_PUBKEY_bioi2d_DSA_PUBKEY_fpi2d_DSA_SIGi2d_DSAparamsi2d_ECDSA_SIGi2d_ECPKParametersi2d_ECParametersi2d_ECPrivateKeyi2d_ECPrivateKey_bioi2d_ECPrivateKey_fpi2d_EC_PUBKEYi2d_EC_PUBKEY_bioi2d_EC_PUBKEY_fpi2d_EDIPARTYNAMEi2d_ESS_CERT_IDi2d_ESS_ISSUER_SERIALi2d_ESS_SIGNING_CERTi2d_EXTENDED_KEY_USAGEi2d_GENERAL_NAMEi2d_GENERAL_NAMESi2d_ISSUING_DIST_POINTi2d_KRB5_APREQi2d_KRB5_APREQBODYi2d_KRB5_AUTHDATAi2d_KRB5_AUTHENTi2d_KRB5_AUTHENTBODYi2d_KRB5_CHECKSUMi2d_KRB5_ENCDATAi2d_KRB5_ENCKEYi2d_KRB5_PRINCNAMEi2d_KRB5_TICKETi2d_KRB5_TKTBODYi2d_NETSCAPE_CERT_SEQUENCEi2d_NETSCAPE_SPKACi2d_NETSCAPE_SPKIi2d_NETSCAPE_X509i2d_NOTICEREFi2d_Netscape_RSAi2d_OCSP_BASICRESPi2d_OCSP_CERTIDi2d_OCSP_CERTSTATUSi2d_OCSP_CRLIDi2d_OCSP_ONEREQi2d_OCSP_REQINFOi2d_OCSP_REQUESTi2d_OCSP_RESPBYTESi2d_OCSP_RESPDATAi2d_OCSP_RESPIDi2d_OCSP_RESPONSEi2d_OCSP_REVOKEDINFOi2d_OCSP_SERVICELOCi2d_OCSP_SIGNATUREi2d_OCSP_SINGLERESPi2d_OTHERNAMEi2d_PBE2PARAMi2d_PBEPARAMi2d_PBKDF2PARAMi2d_PKCS12i2d_PKCS12_BAGSi2d_PKCS12_MAC_DATAi2d_PKCS12_SAFEBAGi2d_PKCS12_bioi2d_PKCS12_fpi2d_PKCS7i2d_PKCS7_DIGESTi2d_PKCS7_ENCRYPTi2d_PKCS7_ENC_CONTENTi2d_PKCS7_ENVELOPEi2d_PKCS7_ISSUER_AND_SERIALi2d_PKCS7_NDEFi2d_PKCS7_RECIP_INFOi2d_PKCS7_SIGNEDi2d_PKCS7_SIGNER_INFOi2d_PKCS7_SIGN_ENVELOPEi2d_PKCS7_bioi2d_PKCS7_bio_streami2d_PKCS7_fpi2d_PKCS8PrivateKeyInfo_bioi2d_PKCS8PrivateKeyInfo_fpi2d_PKCS8PrivateKey_bioi2d_PKCS8PrivateKey_fpi2d_PKCS8PrivateKey_nid_bioi2d_PKCS8PrivateKey_nid_fpi2d_PKCS8_PRIV_KEY_INFOi2d_PKCS8_PRIV_KEY_INFO_bioi2d_PKCS8_PRIV_KEY_INFO_fpi2d_PKCS8_bioi2d_PKCS8_fpi2d_PKEY_USAGE_PERIODi2d_POLICYINFOi2d_POLICYQUALINFOi2d_PROXY_CERT_INFO_EXTENSIONi2d_PROXY_POLICYi2d_PUBKEYi2d_PUBKEY_bioi2d_PUBKEY_fpi2d_PrivateKeyi2d_PrivateKey_bioi2d_PrivateKey_fpi2d_PublicKeyi2d_RSAPrivateKeyi2d_RSAPrivateKey_bioi2d_RSAPrivateKey_fpi2d_RSAPublicKeyi2d_RSAPublicKey_bioi2d_RSAPublicKey_fpi2d_RSA_NETi2d_RSA_PSS_PARAMSi2d_RSA_PUBKEYi2d_RSA_PUBKEY_bioi2d_RSA_PUBKEY_fpi2d_SXNETi2d_SXNETIDi2d_TS_ACCURACYi2d_TS_MSG_IMPRINTi2d_TS_MSG_IMPRINT_bioi2d_TS_MSG_IMPRINT_fpi2d_TS_REQi2d_TS_REQ_bioi2d_TS_REQ_fpi2d_TS_RESPi2d_TS_RESP_bioi2d_TS_RESP_fpi2d_TS_STATUS_INFOi2d_TS_TST_INFOi2d_TS_TST_INFO_bioi2d_TS_TST_INFO_fpi2d_USERNOTICEi2d_X509i2d_X509_ALGORi2d_X509_ALGORSi2d_X509_ATTRIBUTEi2d_X509_AUXi2d_X509_CERT_AUXi2d_X509_CERT_PAIRi2d_X509_CINFi2d_X509_CRLi2d_X509_CRL_INFOi2d_X509_CRL_bioi2d_X509_CRL_fpi2d_X509_EXTENSIONi2d_X509_EXTENSIONSi2d_X509_NAMEi2d_X509_NAME_ENTRYi2d_X509_PKEYi2d_X509_PUBKEYi2d_X509_REQi2d_X509_REQ_INFOi2d_X509_REQ_bioi2d_X509_REQ_fpi2d_X509_REVOKEDi2d_X509_SIGi2d_X509_VALi2d_X509_bioi2d_X509_fpi2o_ECPublicKeyi2s_ASN1_ENUMERATEDi2s_ASN1_ENUMERATED_TABLEi2s_ASN1_INTEGERi2s_ASN1_OCTET_STRINGi2t_ASN1_OBJECTi2v_ASN1_BIT_STRINGi2v_GENERAL_NAMEi2v_GENERAL_NAMESidea_cbc_encryptidea_cfb64_encryptidea_ecb_encryptidea_encryptidea_ofb64_encryptidea_optionsidea_set_decrypt_keyidea_set_encrypt_keylh_deletelh_doalllh_doall_arglh_freelh_insertlh_newlh_node_statslh_node_stats_biolh_node_usage_statslh_node_usage_stats_biolh_num_itemslh_retrievelh_statslh_stats_biolh_strhashname_cmpo2i_ECPublicKeypitem_freepitem_newpqueue_findpqueue_freepqueue_insertpqueue_iteratorpqueue_newpqueue_nextpqueue_peekpqueue_poppqueue_printpqueue_sizeprivate_AES_set_decrypt_keyprivate_AES_set_encrypt_keyprivate_RC4_set_keys2i_ASN1_INTEGERs2i_ASN1_OCTET_STRINGsk_deletesk_delete_ptrsk_dupsk_findsk_find_exsk_freesk_insertsk_is_sortedsk_newsk_new_nullsk_numsk_popsk_pop_freesk_pushsk_setsk_set_cmp_funcsk_shiftsk_sortsk_unshiftsk_valuesk_zerostring_to_hexv2i_ASN1_BIT_STRINGv2i_GENERAL_NAMEv2i_GENERAL_NAMESv2i_GENERAL_NAME_ex @` @` @`8 p2 , 8 , ;<P<?@`Bd@ p Pl `X H 8 (    e d  8 @  P `܂ pȂ   @    l  ` X L 8 0, @ P ` p؁ ȁ  `  t P\ L 8 (  p  Ԁ Ȁ     0 d e rp fT gH h8 i n j s o k l t p q mh  0`p 0ؠ  Ƞ   @ 0    t d  T < (  P ` pП        p ` T 0@ @$ P ` p؞    @ h H (        d L 0@ @0 `  p     Ԝ     P `t ph H 0 P  d e f؛ gě h j k lh mX n<  o z pؚ | } { | X @ 0     Й     l ~T x@ , i   qԘ  y  X r@ 4 (   З s t ul X v@ ,   ؖ Ȗ w d ` @  @ P  |  l  X  < p , p    0 @ P ث ` ȫ       x  d  T  D   < f 0 l m  d < h  j e ܪ g  n Ī o k i Ȭ `!#&& %@  %0  %$ 0 % @ % @% P% `%ش  %ȴ % p% % % %| 0%p %\ %P %@ %0 % % % % %Գ % % @% % % %t %\  %P %< %0 0% @% P% P% `% p%ܲ %Ȳ % p% % `% %l %X %H %8 d% n% q% r% e%ر f% s% g%| m%d o%X t%@ h% p% i% j% k% l%x h  @C@DEEHOIK SUVPW`W`ȸ P    0| @` P @ 0    @ p з   e m j h f l| n@ g ol k dX i P     l  X  H  4 @  P  `  p      0  @  P x ` `  L  8  $              t 0 `  <   0        0 d @ 8 P ` 0   @   pt T @8   ` p  | ` 0       P  `  @x PT `8 p   p    \ ,         | d  L  4             l  T < $      0  `  @  P  P h X H  8 0( p  @ P   ` pp X  H 8 $       p D (   @            p  0 h P  @  , P  `    p      s t  d| ` uD  v, w   x̿ y e p nh mP @  f, g h z ܾ {Ⱦ  | |ܪ }  l ~\ o L  4  j k l q̽   r  p d    p 0"4"8"<"  1`+T @+@ P+( f+ g+l d+X e+   ;70>* @* P* `* p*p d* e*< f*d g*ܪ j*Ī k*l h*D i*, pH @8 $ P `   @  P  ` x 0 d p X  D  8                            p  d   X  L 0 @ @ 0 @ $        P  `  p  d  e  f  |  g   x h d i < j  k  } l  {  m  n  o  p  q t r `  P s @ t 0 u  v  w  x  y  ~  z   pWV0ZYX`VV Z:Z:ZpZv ]p]0^`^[@[`[ @`_0ed`_0_, j jkh`hh 4 qqvq pput wvPwvv  zx{wx  pХpТ pPw0$ PH @@ 0P$" `$" @$" f$" g$p" e$T" d$D" ) ) ) ) ) x) `) D)  4)  $)  )  ( ( ( ( (  ( !p( "\( #L( $4( %( /( &' '' -' .' 0' '  ' 0 @, P' `' p' ' x' p' h' \' T' L' D' <' 4' ,'  $'  '  '  ' & & & &  & !& "& #& $& %& && '& /|& :h& ;P& <4& =& >& ?% @% A% B% C% D% EP% @P`p|pd% edP:`p `:Зp l `pP F xFPhF `F PF >>>>o>|>h>T>fD>x4>>>gܪ ===t===h=i`=X D=u(= =<j<<<<y<|<d<kP<{8<|<l;};v;~;m;n|; PHP0       `  ??`@@@AAA A@BWV$0]]]]]]]]]]]]  |   d Э <  @ @     `k` @ P ` p ܇ Їp     x ` T @ 4 (     Ԇ     x0 h@ XP L` 8p $    Ѕ  ` 0  tp `P L 8 (`    ܄ ̄  0   x  `@ HP 40   ` ܃p     x h X H@ < $   @ ؂ Ȃ    t d P0 @@ 0P ` p   ́     | p ` P0 < ,  P 0 @ ܀ ЀP `  ` p  pp X D@ 4P (          t \d Pe Df 0g h  ~i ~j ~k | l ~ ~m ~n  o ~ p~ L~p D? 8~ ~q ~r }s }t }u }v }w x}x X}y H}z 4}{ $} } || | | | | | |} x| d| T|~ <| | | { { { { { x{ d{ T{ <{ ({ { z z D> z z z z z tz \z Lz 4z z z y y y y = y y xy dy Ly 4y y y x x x x x px Xx Hx 4x x  x w w w w w tw dw @w ,w w v v v v P< v |v hv |; \v Pv 0 $   0  ܓ ē@ P `   p x h ` TP L` <p (  @  `  p    h P < ,      ؑ0 đ@ P d e \@f pg `t Lh u 8v $ s w ؐx y z { xi hj Xk Hl 8m n | } o ؏p ȏq P<r ~ :@ ,P  ` p  Л  p   p P 0   0 ̚   p@ X D 0   0 ܙ0 @ P ` p x h L 8 $    ̘  `  pP ` P <d (v r e f ԗq w { s t tg `h L| >i ,} ~ j k Ȗl u m dy x lo d<p Xz Pv  0 0 x0 h0 X H 80 ,  p   xm xph\TL@8$ԧxhTH<4$( ( P) `) XȪ8pHب0h<@ Щ lx`$@ " "t "T"H"< "0"$p"p "@ " "ض"ȶ"P """p@"`P"T0"D` "0 "$ "@"""ܵ "ȵ0" """"l"X"D"00 "P""p"ش`"`"p"`"P"t "l "X "H0 "0 " " " "Գ@"""""p"`"P "<"(""""Բ"v"w"d"e"x"h"P"<"$"""ܱ"ȱs"f"g"|t"d"Lq"8""""h"Ȱi"""j"tk"\l"Hm"4"T{"$n"""ܯ"""""|~"h|"Lz"H"4y""""Ȯr"}"p""t"d"D"0" """z"{"do"H"4"x" u""hv"xhXD0$Ծľ | l\@ 8,    p Й  x 0 dT0.@ .@.P . .P.l`.\p.D.4.........` .d .L0.,@. P.`. .p....d.H.,..... .0.@.pP.` .H ., .`.p....|.\.<...p . . .t .X .<0 .(@ .P .` .p . . . .0 .l .` .P .Dc.0..d.e.f.g.h.|.`i.L.4j.k.l.m.n.o.p..|q.`r.8s.$t.u..v.h>w.x.y.l.X.4...z.{.|..}.~..|.y.=.=.t.d.P.8. ..........d.T.@.,.......<..x.T.8.....hv....t @`p@p0P`xhXD0 Pnsd|ehoPp8mf ijkrP lgqh@@ @ B C H `C I `H H H PO B 0C H `C I `H H H PO !| !l !T !< p! `! @! P! `! 0! p! !| !` !T !@ !0 ! ! ! !P!@!0!`!!! !h!T!@!,!@!!!!!p!P!!t!(u!!~t!\v!@!! d! w!e!!!x!y!!x{!!z!z!zg!lz!|!y!=!L!y!xys!(! {!!!dyh!|!!~!}!p!`!L!4!i! !d!!!px!@j!k!l!m!xn!do!Lp!8q!8r!$#p#@##l`#P#8#(## ##P#####l#\ #H0#0`# p# ### #0###|#ld#Xy#@e# f#D?g#0x# h#\i#j#k#l#m#n#o#p#pq#\r#Ps#0t#u#v#w#0)\@)LP)<`),c)d)e)|s @  l@ &P &` &p &x&l&\ &@&4 &$ & && & & &0& &| &d@&Tp&H&8&$` & p & &&& &&&x &h &P &< &$ & & & &&d&&&&t&\g&Dw&$&&h&&&f&i&&x&\&@j&0k& l&m&n&& &&&&u&xp&lx&X&L}&8&(t&~&q&&&&e&&t a@ 0   $!!@'1`'0p'0'0'0P'0'0'0'l00'X0'D0 '40' 0@' 0'/'/P'/`'/'/d'/e'f'/z'p/{'T/y'@/g'$/|'/h'.i'.j'|k'l'.m'.n''.o't.p'`.q'L.r'4.s'.t'.u' v'd}'-~'-'-w'-x'd'-(2(l2@(T2(L2P(82`($2( 2p(1(1(1(1(1h(1f(1g(p1i(\1d(H1e(41j(120Y pX \ Y 0 /8H/(H/H/H/G /GP /G@ /G0/G@/lGP/TG@/@GP/0G`/ Gp/G/F /F /F/F`/Fp/|F/hF/PF/8F/ F/F/E/E/E/E/E /tE0/XE@/SK?NvہTG= `yȱ4g|"UCР;X)z`KQ'nU_O_MKaLۻ{*z'9AYst t ^yU /)f:`ϰgi9PکH 1K#=gwu홠)sP`=1er/X^fJ2Ak@_@@h```: тK[C1tOFٺ wl]azW {+Rdj>svd/k&Νa%J3 یᦅ} ]Wq Xd߫!U3zP 3-ĪZr&j|I9X+RLo]ŵ좃',w;6.F^2|!ltJN5 gmp)՞R Vb#]e_$?iU6Hژc|=[Qf(IK|$Zk8\ k7BL~^bvEQmm5O7_m +0C:ͳ4yJQ"; tgN)܀b4h!145Mܷݏ괓Z'Hp!vp)a[Q;#ÐO]kNGY|(ʾ.»L*% 4hsvd/k&Νa%J3 یᦅ} ]Wq Xd߫!U3zP 3-ĪZr&j|I9X+RLo]ŵ좃',w;6.F^2|!ltJN5 gmp)՞R Vb#]e_$?iU6Hژc|=[Qf(IK|$Zk8\ k7BL~^bvEQmm5O7_m +0C:ͳ4yJQ"; tgN)܀b4h!ad$@mtt [-`H?f>hZ'1'Sj0A/8S7=vuF&`&p|Ҵ645Mܷݏ괓Z'Hp!vp)a[Q;#ÐO]kNGY|(ʾ.»L*% 4hsvd/k&Νa%J3 یᦅ} ]Wq Xd߫!U3zP 3-ĪZr&j|I9X+RLo]ŵ좃',w;6.F^2|!ltJN5 gmp)՞R Vb#]e_$?iU6Hژc|=[Qf(IK|$Zk8\ k7BL~^bvEQmm5O7_m +0C:ͳ4yJQ"; tgN)܀b4h!݀`qnVߔVvP0wVGXGn +8.lHC @F5hksM~ձ~]HFd]%E6jt1-D?*mx<+:[3hyK݅/Kk0lds4#W|.""ي-e#x+t#4hZc:f$kv%Gtӝ2;1sľ،2|w8otYmtt [-`H?f>hZ'1'Sj0A/8S7=vuF&`&p|Ҵ645Mܷݏ괓Z'Hp!vp)a[Q;#ÐO]kNGY|(ʾ.»L*% 4hsvd/k&Νa%J3 یᦅ} ]Wq Xd߫!U3zP 3-ĪZr&j|I9X+RLo]ŵ좃',w;6.F^2|!ltJN5 gmp)՞R Vb#]e_$?iU6Hژc|=[Qf(IK|$Zk8\ k7BL~^bvEQmm5O7_m +0C:ͳ4yJQ"; tgN)܀b4h!g$k PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGX00090C0K0Q0W0\0f0{000000000000001 11151L1Q1W1_1t111111122#212C2Q2c2q22222222233#313C3Q3c3q33333333344#414C4Q4c4q4444444455!5O55555560676M6y66666677%757A7Q7j7u777777788888889 9"9+9<9I9O9Y9s99999:>:H:Z:c:j:o:v::::::: ;;{;;;;;;<<">=>Q>k>>>>>>>>??+?F?M?w???????????? 00 0$0H0M0R0X0^0d0j0p000000000011(11171=1\1`1j1|111111111 222*2I2Q2g2z2222222333A3Y3^333333a4444565>5a5y5~5555556M6W6w6}666666666 77$727:7C7L7U7`7v7777777778%818889^9u999999999 ::3:;:@:M:v::::::::1;H;a;m;;;;;;;;; <<<&<1">9>A>F>S>q>>>>>>>?A?S?\?e?n?y????0x00G0O0X0`0k001+1>1P1Y1b1k1v111112A2c2|22334'484O4h4t4444444445.5@5N5T5]5p5u55555555555 6<6O6f66666666667,747=7E7P7f777778)84898@8M8X8]8g8t888888888888899+969E9g9~9999999::9:k:::::;;;;;;;<<<$<3<=<<<<<<<<<<===(=9=R=_=q=z=~==========>>1>:>>>H>Y>r>>>>>>>>N???@H+0I01S1112222333366 7&7W7q7777788U8r8{8::F;P 58p9$:7??77K8l8 9 ; 7::+;;;<<;=K??$1e13#4y4t5 7777V;3<< = 0x555555555(6H6778&888n8x888#9A9U9g99999S:q:::::::;;;;;; <>> >>>>> >$>(>,>0>4>8><>@>D>H>A??401G234444 4$4(4,4044484<4@4D4H4L4P4T4X4\4`4d4h4l4p4t4x4|44444466666677"747@7R7n7t7|7777777]8k888888889919@9_9999:!:):;-;R;a;o;;>&? P4080<0@0D0H0L0P0T0X0\0`0d0h0l0p0013566 6$6(6,6064686<6@6D6H6L6P6T6@ J6PL1R1{12257t8x8|888888888888889h:l:p:t:x:|:::;?`X(0,0004080<0@0D0H0L0P0T0X0\0`0d02;35R5k59d<<<<<<=== ===== =$=(=+?p14K5?4233 3$3(3,3034383<3@3D3H3L3P3T3k5Q7:;l9J7>E>P>W>u>>>>>>>>?? ?'?.?E?X?h?s???????0!0,030`0o0v00000000000111$1/1A1H1S1}1111111222_2f2t2222222223 3313?3M3d3r3y33333334 44!4(4G4W4^4r4444445#5-585?5[5s5~55555555555!6,636C6Q6|66666677)7a7z77777777788&848B8[8b8i8p88888888 99:9U9e9p9w999999999::#:*:;:Q:X:_:f:q:::::::::&;1;I;V;];;;;;;;<"<0<7<>>3>B>L>_>~>>>>>>>>>>>@0G0P0Y00000000011%1.1\1c1l1u1111111121282A2J2x222222223 333M3T3]3f333333333+424;4D4r4y4444455>5E5N5W55555555566#6,6Z6a6j6s666666667/767?7H7v7}77777778 888K8R8[8d888888888 9'90999=q??40]000.151O1V1l1s155566,666::;< {1 78012]222P\:m:~::::::;%;6;B;];d;u;;;;;;<<< >I>Z>k>w>>>>>>>??7?>?M?[????????`0<0C0T0`0000000 110171F1P11111111132D2U2a2|222222223$333A3w33333333$4+4:4D4a4h4w4455%5/5M5T5c5m555556!606:6Z6a6n6x666666667%7,7;7E7_7f7u7777777788*818@8J8{8888888888 99F9M9\9f999999999::%:/:M:T:c:m:::::::::;!;.;8;O;Y;k;r;;;;;;;;<<"<1<;=M=W=u=|======== >>">@>G>V>`>z>>>>>>>>???)?=?J?Y?c?????????p00$0.0\0f0u0000000000&1-1<1L1^1r1|111111222233$3.3@3Q3^3h333334"4/494T4^4m4w444444445 5'565@5s5z5555555556 6<6C6R6\6|66666666777'7E7L7[7e77777777788$8.8H8O8^8h88888888899,939^9k9z9999999999,:6:E:O:j:t:::::::::;;6;=;L;V;m;w;;;;;;;<<'>6>@>^>e>t>~>>>>>>>> ??2? 02</2u2R99::%:D:I:h:n:::::::: ;;<0`>d>h>l>p>t>x>|>'?@22222222256 9\9f999R:]::;;;<<+>??020r0~0000b111G3N3b44f<<<===3? $700+2?2266607A7W77:=0$E455577t8z8::???@4r7b9`|1B:<?p6-7L7^77788y9(233#3=3O3a3n3w577P88> ??P801J33(4a4q44445566,7q77,9B9h9999 :Q:h:/=>=Z=r=w===D>[>\111111n2223*4x555556;6[6: ;T;; <>>>!?=??80002K3333N5555666 6`66 7Z778888TD0F1333444L4Z4}445677 9W9{99:,::E;b;;z<<,=B=H=R==>?#?9???\00111C112&2P2}223334C44g55556)6q66{888m99:::T<<=='>??d0a0n001#1C1f11S2222 3'33304456G6z66t8-9P9|99a:q:::::: ;);M;i;;;3==P>>p00 1#1(101F1K1111122L3f33333.4T4[4q44444 555"66666666/7g7778`888<3= >>`00s233<4C44Q5n5556l6p6t6x6|666666666667T7778H88889C9d9h<D7!7/777777E899z;;;;m<<<<<<=6===S>>>>> <09334F406677868S88:;1;\;;;$<<? ?-???0G0d000001182223,3D333)556|666666666767V7a8x9::::::;;';>;;;; <@>>>>?V????@]0001!1n11111E2t22222313`3|3333333"4O444415i5555556I6f6t666666 777O8p8t8x8|8899!9E9_9}9999999991:6:F:P::::::::*;1;S;Z;;;;; >>S>>3?b???PP 0@0Y000111w223:456667778868D8g88s9Z:<<<==>">>?`\200 113 33 3c3333334c66v77788p999:9:S:;`01132223333484X455!677L777/88809O9+::;;;;;LT>>U???\ 050034444G557778888888M991:Z:|::;;b;~;=b>>z?O00011%2x222222233)3334N4i444+5N5~555627O7m7;8L8i8889[9~99999-:>:Y::::5;V;;;;M<=t===)>^>?D?d???0H00081a1142]2x222223[33334)4P4c444455(5K5l55555P66677E77778*8M8v888829Z999::::0;s;;;(*?,e0071d11 2?22z335 6C89o;;;a5~:?P 0b00V111p223*444N55556~8888989U99::<<=>)?0???X0005000a1k22w3~33334558H888888 939A9\9u999:F=== >>>]? L0d112223B5b5O6678D99::;<'<<=>>>>>??,?_?00 0070<0A01F1112223X3!434>4U4a4o444444555555m77777,8899o::::;;?>>?@T|000'1{1114C4N4c4z45P5b5w56R6g6657I7'8=8888`9y::9;;;><<<1==_>P001?222222&3E3|33334)4;4M4U4g4y4444444555 5555555555,6@7772898999 99999 9$9(9,9a:::::;;;;;;;h}>>>?\?d?????`0 00k0{000001)1F1Y111112@2L2a2t22222223 33#3k333444 44444 4$4(444m5}5555666666666 77I7r777!8288888T9X9\9`9d9h9:/:E:c::::c;a<<<<==-=3=D=r==>3>P>V>l>r>>>>>>>>> ?/?E?K?\??????????pp0e0o00081J1111*2122q3385<5@5D5H5L5P5T5X5\5`5d5h5B667778;;<-=Z==??? ????? ?$?(?x0!11K2{22233455,6~6839:999m:t:!;(;=====>>> >>>>>4>8><>@>D>p>t>x>|>>>>>>>>> ?:???012/2m222A333%4r44444455$5:5z555:6z666777\777777777788%8B8R8X8;99999: ::":k:x::::;7;];;;;<>:>>>>e????00H00000011"151;1L1i1|111111111"2Q22222444455<7@7D7H7L7P7T7X7\7`7d7h7l7p728{888;;O=>?,?Y?s??0/0P111A223353444444444444444555 555555[6e66667788979@9F9999999::: ::::: :$:(:,:0:4:::a;g;p;;&^>>.112556687H7788 99+9:9L9[9j9y9999999::::;;;;;<< <<+<7<[,>>>>? ??#?1?7?L?_??D0*080G0^0d0q0w0000000 111 1*141>1H1X1c1n1t1~11 2-2g22222N3b3v3333K4a4t4444444445 5"5,5a55556]6666666677777A8Q888888889&9.9w99999999::!:?:V:i:q::::::;*;A;_;v;;;;;;<<1>7>u>z>>>>>>> ???>?W???????Xh00000011111111222(232>2I2T22,333/4Y444445V5|555556w666666666666a7o7777777777W8g8~88888888889"9/9A9J9N9X9i999999999 :%:C:b:o::::::::';7;N;S;];b;o;y;;;;;; <<$<(<2>2>?>D>S>t>>>>?N?r????????????0020?0Q0Z0^0h0y000000000 11$1(121H1|1111111 22+24282B2X22223 333*3X3e3w3333333333404Q444444555(5955X677 888"838S8t8~8888888999(9:9A9H9_9e9r9999999;; <(>??80e00J1w1K222333424<4K4[4k4{444444 575P555566 77?7H7]7s7}7778 8"8.838C8M8Y8q8889 99(9P9e99999::&:W:u::::;;;;<=== ============>>>O>V>[>o>>>>?"?o????h'0_0s0}00011Z113!3N3W334@4Y4h555 6i8S9999:C::::;;I< =+====>??r???? | 0.0[0h0000000001%101a1j1y11122)262Z2k2223*3t3333446?6U6_67u88#9=9\999;M>??0d0112]2g22233-44 5#5516666*747o777$8(8,8084888A9I:R:X:a:s:|::::{;;;;;@\11122!2Q4a4q44q6666:;;!;1;A;Q;a;q;q<====>>!>1>>>>>?????P10f000[1b11111x22w33333S4o4v4455/5E5g5n55558888889 99"9+929B9K9R9b9k9r9999999999999: ::":+:2:B:K:R:b:k:r:::::::::::::; ;;";+;2;B;K;R;;;F<>>>>>??? ?[?x??`t33"323;3B3R3[3b3334A4b4|4455555555777 777[7778:::::::::?>;?TG0y012`222 3444444f556O888 9a9;;<< <<<<< <==%>/>X>b>0111122t2~22222/3933333 44)4P4Z4n4x44444 55555536=6D7H7L7P7T7X7\7`788;;t=x=|=======>>>>?????????0000000001 1X1b1o1y11111112$2.282B2L2V2`22222S3]3g3q33333d4n4x444444;5E5O5Y555555555666$6.686c6m6z66.777<8C88888999 999999!;8;k?l81o3v3444444444+5q5555 6o66664788888+99999A:F:U:k::::;; <[<>>>?d 2H2g2q22!3M3b33y444.5f55555A7J7W7v7,8\888 9m99;; <6[>>>P???T%0000c112N223_334`444S55 676c6660777 8^8809q99T:k;<=k?H+12+33m5D666667k778&8@8x999:1::<<===x????D21L1133~44556q666667z88j9o;;(=F==,>T>e???HF0-444446w66678/88'9":c:;6;G;X;{<>H????@1J1b11,7L788(8:899u::;>;;;=R=h= >>)?I??? L0q2w2 3r3}333344.4S4g4}444}555556636B6l666666777 777777-8v8889{99<;@;D;H;L;|;;;5<<===#>[> ?-?9?R?z????00L2222$3333333494V4A5]5y55555616E6o666667P7y77777 8:8Z8888#999:::;;q<<<<&>A>Q>m>>>>>>B???@001L2a2}2222233-3I3a3u3333\44\555556667277778*9a9s99::;;;;;< =)=A=U=v==!>L>>>>>>B??P01t111112%2A2Q2a4}44444 5!555]5y55556F67778888Y9::3;J;;; <)>>m>>>??`0001Z11n2222223;3^3t3y3333 44C4H444444445595]5566[6w666h7777W8y888u99999:::<=(=4=X={>>>>>y???pq0000011'1F1M1S1X1112;2S2222353K3P33333h4 515@5F5n5555556g6x666666666)7E7J7~77777777788H8^8s88849;9k99999Q:::::: ;;<;n;;;;;;<>>>>>0??p4000000111 1#1x1|1111110233h3l3p3t3x33X5\5`5d5h5l5p5I:(;,;0;4;8;<;,?!0b0015112]223#334@4U5p55G6s6y6666666666l77v88899:;!>=>Y>q>>>>>>?!?=?Y?q??????0010M0i0000001111M1i1111112212M2i2222223313M3i3333334414M4i44444445%5A5]5y5555556%6A6]6y666666677-7I7m77778-8~88888[9|9999:;C;J;; <@>>Q?W?????????|#0-0;0A0_0e001 1$1*11111"2B2T2a2b3w333334&466778899k:::: ;s;;<<===>I>e>>>>>N?e??tF0a0001 1/11112223)3333444O5t55555656K666788Y9~9999::s<====>1>E>m>>>>lH0O0\1`1d1h1l1p1t1x13933`4j4H5L5P5T5X557777778899:#:*:1:S:d:::%;;;;\=c===d>>;?o011G1U1n111/22=3c3R4444?5>66074787<7@7D7[7777777 88'8C8S8d88888889,9B9V9]9k9p9v99999999h::::*;y;;;;;/2>B>{>>>?P?j?v????>0c00001<1@1D1H1L111Q2V2[2u2~22223333 44r4485?5e55555555556646W6n6u666"7;7777758V88889_9999':A:d:h:l:p:t:x:|:::A;`<>/?5?K?a?h?????`001411z23>333d4444D555616:666667Z777L:a::; ;<+K>i>>>)?????0x00=0Z000"1;1111212E2a2}2222213404C44445666q77777'9-99R:::::D;h;;c>>?@l3000151l111112m222356]66677e88888 999)979S9}9999;::;;<=~====?>!?U??PQ0`000091112Q222X3334V4449526f666 7:77778R88889N9999:N:~::Y;;;;A<<<)=3=L=k==>??C?W????`0{00K122u3z333334 454:4e4j4444444%5*5U5Z555555566E6J6u6z666777788E8J8u8z888889 959:9e9j9: :D:I:u:z:::::; ;;;;;;;%<*<<<<<==E=J=======%>*>U>Z>>>??E?J?u?z?????p0 050:0e0j00000000%1*1U1Z111111122E2J2u2z22222a33445 555:5e5j5555555%6*6U6Z6{66o778\88K99/:4:{::Z;< =f==e>>(????<e00*1k11 2|2 3333444578R:<-={==Z>s>>@101F2r22444I5556Y66779::::;;!;"<+=?P0&2;2m2+44466,77788889989<9@9D9R999;<<? ?( 8899-;;(>=??126$7d77:;d=4?2|222223?3V3m3333777::==Q==?(^0Q11S556?7A88899Z;=>>T500I1g11445556#6b6666667^777@8o8889(9i99:0:y::::i;<< k1p11+202k2222222 33+3K3P3k3333333 44+4K4P4k4555566;6@6[6666667 7;7@7[7777778 8@8E8K8Q8W8]8c8i8o8u8{888888888888888888888889 9999#9)9/959;9A9G9M9S9Y9_9e9k9q9w9}9999999999999999999999999999::: ::::: :$:(:,:0:4:8:<:@:D:H:L:P:T:X:\:`:d:h:l:p:t:x:|:::::::M;z;;<*>>? x001<1S2222353q334T444L55F66666%7r777K8x88V9999/:::: ;N;;;<,Q?_?l?????? 0010:0I0q1111112<2U222?3X3^3d3w34 585Q5W5]55'6x6666)777c7|7%8e8 9{9995:P:_::;4;N;;;<<@<==%=>0 A0]0y0000O111111$2:222@3M3i335j666667 77C7z777778<8B8Z888888C9K9_9|:::x;~;;;;< <3<9(>K>>>A??@ t000021f1112>2r2223(3.3433333u4444 565S55555D6x66637:7999:w:<>>>+?@???P $0000 1)1A1U1q111111 2)2A2U2q2222222`3p3t3x3|333333333333333334$5(5,5054585<5@5D5[555555555 6)6X666757I7N7z7777777777778!8B8c88889.9D9_9y9999999999Z:w::;;;;N<_<<<===>.>q>>>>&?4?`?d?h?l?p?t?x?|??????` 0%0>0W0001E1^112a2z222 333N444"555A667J777b8s888S9999 :!:5:[:a:z:::A;];y;;;;;;<%<[ >x>>>>>??p 3000 1)1A1U1q1111112292Q2e2222223393Q3e33330464P4W4]4c444445D555!6{666 7[7x77777738>8R8c88888889 9969<9U999:k: ;%;?;[;a;g;};;;;<<<<<====>1>P>V>\>u>>>>>>?W??? e000000011q111111 2)2A2U2q222222 3)3A3U33333344<44444444445$5d5555666J777 886888.9D9::;;2;\;;;#>J>Q>f>>>Z???? hT0]0j00111\11144455064686<6@6D6H6L6P6d7~7q;;;;;=>;>?"?e?? 0V0001'1;1W1q111122>2V2\22222334 4m4s4444A5]5y555555566X7777777 8858;8A8a8q888889P999:.:4:::M:q:::::::E;L;k;r;;<<<_K>>>>>x???? 030o0000000013-3I3a3u3333334"4C4Q4\4b4y4444445S5Y5_555556&65666666M7x7~7777777M8e888D9`9f9~999998;[;p;v;|;;;;;;<<<=c>|>> (a0y00$2~2 33a304<<g>? #0111 1$1(1,1012)3P3T3X3\3`3d33333333455677X8889:::;;;<<<9=T=X=\=`=d=h==?>{>>>>>>>>>>>>A?Q?a?q????????? x00!010A0Q000011!111_11111111122444%5*5U5Z55566 77O88899j::::a;;/<\=!>J>`>?? D00I1112263f3?455J66=778#8.8^88Y:u:;0? D0>11'22K33Q444m5]889x999:M;;;<<<==>>? h0001N111=22333334o444A55566+7q777Y88.99L::;;2">>>? `0K0001"2;2q2 3=333c444R66L7K888+9z99:v::;-;;; >>>@?y?0 |0B124333]444Z5s556Q6c6n66666N7~777(8F8W8]88.9[9i999@:Z:h:::;;I;{;;;`>|>>>V??????P %0m000000d1r11A2G2x22222334#4P4`4f444444 5L5]5555556#6D6|666628g8~8889T9s9C::::;;;=;C;M;` 10Y000000001%1I1f111111!2=2Y2q2222223!3=3Y3q333334%4A4]4y4444445%5A5]5y5555556%6A6Q6r66677b9x9|999999::#;D;;;;< =0==6>>Q?p X20I0o01=11222 222283p33G444555666+7 8::::::.;;<<==u> L131A22445O66'7M88899.:::;;<==U>>>>>>?F?z??? XG0/1111-2223q334R4444)5^5~66'7A7]88949Z9 ::;-;H;;<<<=O==_>?? d,0011?223j33344556696Q6e66666677-7I7a7u7777778!8189l::P;;k>? `0!1[1112222 3H33;444 5o555K6[6r669:;=== =====>>M>>>>??? \-0[00*11[2w223B4{44 5T55C6k9::;;;;L<}<<<<<0====???1?????? 00021F1V1r1111111 2~22334'4`4f4q44444445<5\55556"6C6]67,7:7777888.8B8G8\8r888889'9I9`999999 : :U:}::::C;f;;;;>>/?E?[???????????? 0A000111B2j22223<3t3333344g4$5N5566g6666h77/8889!9=9W99999 :,:I::::::;9;cH>_>v???????? /050:0S000000011?1E1J1c111111 222O2U2Z2s2222223!3&3_3e3j3333333+41464o4u4z444445 5;5A5F5555555666K6Q6V66666Z7_777798f888899i9n99 :6:Q:::::9;>;f;I?? 00=00000N1S1c1r1111112 2A2Y2223~3334i4{444*5D5\5a5{5556F6d66666C7Q77A8Z8m8|88888999w9~999999<:E:f::::::;M</>?M??????????? 0%080J0\0}0A1U1h1z1111212E2a2}222222313E3a3}333333414E4a4}444444515E5a5}555555616E6a6}666666717E7a7}777777818E8a8}888888919E9I= X01122`22223=3p33344444_56778889|9K;d;;<7??0 011#2a222245567777777777 8%888?8U8h8o88888897999\::::::;O;e;;;UY??@ hG012~33R4445A556g666<7Z7777777=8m888s9999:];c<<===>>>?"?(?4?>??P 01122224r556*6:6D6N666666 7*787777 8"808a8888888889G9L9Q9W9c9k9v9{999999999::#:.:8:C:N:e:::::::::::; ;;; ;*;;;U;_;j;;;;;;;;;'Q?m??????` 0!050Q0m000000 1!151Q1m111111 2!252Q2m222222 3!353Q3m333333 4!454Q4m444443566k;;;;<<<==-=4=Q=X=n=u===>>>>>>>> ??Z?a???????p 00000000.151g1n11111n2w222222222!3(3\3c333f4o4~44444444455$5A5H5^6g6v6}666666666C7J7w7~788&8-8<8C8Y8y8888889'9.999999:::;:B:::::::;;<<<$>H> @7777W88+99z::::::;;;g; >K?? 001^1l111111222-2U2y2222223%3J3b3{333333333 4"4;4F4^44444#5^5l556?6666%77789::;;;(<<=*=o=>c?? d 030a000N1b11111'2A2g2n2u2_4455S56 66647d777D8n88999U:r::";K;;;<=>4>? 0,0e0000001*101612+3{334444556678:8A88"9)99q::;H;;;;;;;<<;>%>N>S>g>l>q>w>>>>>>>>B???? 4 000!0000 111!1111111162`2f2l2v2233 3363Q3W3]3g3333444(4V444444 55S5^555566696666667C7I7S7s7778%8+818;8Q8m88888899;9@9[9}99999 ::+:K:P:k::::::;-;I;a;u;;;;;;<<11>E>f>>>>>>?-?I?a?u??? L0K0t0000+1{1112 35669:6:Z:h::;;(;R?K?`? 2 446[7 88<99.:4:::@:F:;;<<==$=+=0=F=R=p=x==========>>(>8>>>E>\>b>>>>>>>>?? ?(?S?Z?_?d?k?x????? 0K000000000001 111"1*121>1G1L1R1\1e1p1|111111111}2222222222 33V3[3|3384=4O4m4444445 5&5j555555555566 66 222444444444444444444555 55555 5$5(5,5054585<5@5D5H5L5P5T5X5L >> ><>@>d>h>` <= T7788(8<8P8d8x88 4X2l2p222222222222222 333$3,3@3T3X3h3l3x33333333333334 4$4(4,4044484<4@4D4`4d4h4l4p4t4x466666666666 84888H8L8X8`8h8|8888888888888999(9<9@9P9T9d9h9t9|999999999999:::0:<:D:L:>>>>>>>>>>>>>>>>>>>?????????? 00h6|6666666668999 99999 9$9(9,9094989<9D9 :$:(:0:8:x:|::0;4;8;<;@;D;H;L;P;T;X;\;`;d;h;l;p;;;;;;;;;;;;;;;;;<<< <<<<< <$<(<8<<<@> >(><>@>P>T>`>p>>>>>>>>>>>>>? ?? ?0?4?D?H?X?\?l?p????????????? 000 0`0d0h0l0p0t0x0|0000000000000000000000L1P1T1X1\1`1d1h1l1p1t1x1|111111111111112282<2@2444444 99999::: ::: ,6677 77 7$70787<7H7P7T7`7h7l7x777777777777777777888 8(8,888@8D8P8X8\8h8p8t8888888888888888899999(90949@9H9L9X9`9d9p9x9|9999999999999999:: : :$:0:8:<:P:T:h:l:x:::::::::::::::;; ;(;,;8;@;D;X;\;h;p;t;;;;;;;;;;;;;;;;;<<<<<(<0<4<@>> >(>,>8>@>D>P>X>\>h>p>t>>>>>>>>>>>>>>>>?????(?0?4?@?H?L?X?`?d?p?x?|????????????? 00 0 0$080<0H0P0T0`0h0l0x000000000000000111 1(1,1@1D1X1\1p1t111111111111111122(20242@2H2L2`2d2x2|22222222222222233 33 3$30383<3H3P3T3`3h3l3x333333333333333333444 4(4,484@4D4P4X4\4h4p4t4444444444444444455555(50545@5H5L5X5`5d5p5x5|555555555555555566 66 6$60686<6H6P6T6`6h6l6x66666666666666666777 7(7,787@7D7P7X7\7h7p7t7777777777777777788888(80848@8H8L8X8`8d8p8x8|888888888888888899 99 9$90989<9H9P9T9`9h9l9x999999999999999999::: :(:,:8:@:D:P:X:\:h:p:t:::::::::::::::::;;;;;(;0;4;@;H;L;X;`;d;p;x;|;;;;;;;;;;;;;;;;<< << <$<0<8<<>>>>(>0>4>@>H>L>X>`>d>p>x>|>>>>>>>>>>>>>>>>?? ?? ?$?0?8?> >> >$>0>8><>H>P>T>`>h>l>x>>>>>>>>>>>>>>>>>>??? ?(?,?8?@?D?P?X?\?h?p?t????????????????? 00000(00040@0H0L0X0`0d0p0x0|000000000000000011 11 1$10181<1H1P1T1`1h1l1x111111111111111111222 2(2,282@2D2P2X2\2h2p2t2222222222222222233333(30343@3H3L3X3`3d3p3x3|333333333333333344 44 4$40484<4H4P4T4`4h4l4x444444444444444444555 5(5,585@5D5P5X5\5h5p5t5555555555555555566666(60646@6H6L6X6`6d6p6x6|666666666666677 77 7$70787<7H7P7T7`7h7l7x777777777777777777888 8(8,888@8D8P8X8\8h8p8t8888888888888888899999(90949@9H9L9X9`9d9p9x9|9999999999999999:: :: :$:0:8:<:H:P:T:`:h:l:x::::::::::::::::::;;; ;(;,;8;@;D;P;X;\;h;p;t;;;;;;;;;;;;;;;;;<<<<<(<0<4<@>> >(>,>8>@>D>P>X>\>h>p>t>>>>>>>>>>>>>>>>>?????(?0?4?@?H?L?X?`?d?p?x?|???????????????? 00 00 0$00080<0H0P0T0`0h0l0x000000000000000000111 1(1,181@1D1P1X1\1h1p1t1111111111111111122222(20242@2H2L2X2`2d2p2x2|222222222222222233 33 3$30383<3H3P3T3`3h3l3x3333333333333333344(4,4@4D4X4\4p4t444444444444455555(50545@5H5L5X5`5d5p5x5|555555555555555566 66 6$60686<6H6P6T6`6h6l6x666666666666666666777 7(7,787@7D7P7X7\7h7p7t7777777777777777788888(80848@8H8L8X8`8d8p8x8|888888888888888899 99 9$90989<9H9P9T9`9h9l9x999999999999999999::: :(:,:8:@:D:P:X:\:h:p:t:::::::::::::::::;;;;;(;0;4;@;H;L;X;`;d;p;x;|;;;;;;;;;;;;;;;;<< << <$<0<8<<>>>>(>0>4>H>L>`>d>x>|>>>>>>>>>>>>>?? ?? ?$?0?8? >>0>4>@>D>d>h>t>x>>>>>>>>>????4?8?D?H?h?l?x?|??????????? 0000080<0H0L0P0l0p0|00000000000001 111 1<1@1L1P1T1p1t111111111111 222 2@2D2P2T2t2x2222222222233 3$3D3H3T3X3x3|3333333333344$4(4H4L4X4\4|44444444444455(5,5h5l555556686<6l6p666667 7<7@7p7t77777 88@8D8t8x8888899D9H9x9|99999::H:L:|::::::;;L;P;;;;;;;< (>X>\>`>p>>>>>>>>>>>> ?(?,?0?@?\?`?d?t?????????080,000D0`0d0x00000000110141H1d1h1|1111122L2P2222222222222233 3,30343P3T3`3d3h3333333333344$4(4H4L4X4\4|44444444444054585D5H55555555555 6$6(64686p6t6x66666666777$7(7`7d7h7t7x777788888P8T8X8d8h88888888899@9D9H9T9X9@@66889909D9X9l9999999,>@>D>???p04080P0T0d0h0t0000000012222(282H2L2\2`2l2|22222222222333 30343D3H3T3d3t3x33333555566$6(60646<6@6H6L6T6X6`6d6l6p6x6|666666666667777(7,787H7X7\7h7x77777777777778 8888<8::: ;(;,;H;L;\;`;l;|;;;;;;;<4>h>>>>>>>>>>>>?t????????? 000000001 11,101@1D1P1`1@2D2T2X2d2t2222222222t;x;;;;;;;;;;;;<<<$<(<8<< >> >,><>L>P>`>d>t>x>>>>>>>>>>>>>??$?(?8?x>>>>>>>>>>>? ? ?$?8?L?P?`?d?p?x?????????????H000(0<0@0P0T0d0h0x0|0000000000000011(1,1<1@1P1T1`1p11111111111112222,202<2L2\2`2p2t22222222222223333(383D3T3d3h3x3|3333333333334;;< << <,<< > >$>4>8>H>L>X>h>x>|>>>>>>><<(=,=X=\=`=l=p= 8T0X0d0h0t0x000000000334 44 4,4<4L4P4`4d4t4x444444444444555$5(585<5H5X5h5l5|555555555555666$64686H6L6X6h6x6|666666666666777(7,7<7@7P7T7d7h7t7777777777777888(8,8<8@8P8T8`8p88888888888888 9|:::::::::::::::::0 55 5$54585D5T5d5h5x5|555555555556666$646D6H6X6\6l6p66666666666667 77(787<7L7P7\7l7|7777777777778888,808@8D8T8X8h8l8|888888P22(2,282H2T2d2t2x22222222222223333$343D3H3X3\3l3p33333333333333344(4,4<4@4P4T4`4p444444444444455 5$54585D5T5d5h5x5|555 6$6d6h667 7(7,7D7H7h77700 00000 0$0(0,0004080<0@0D0H0L0P0T0X0\0`0d0p0t0x0|000000000000000000000 11 1D1L1T1\1d1l1t1|111111111111111112 222$2,242<2D2L2T2\2d2l2t2|22222222222222223 333 3$3(3,3034383<3\3d3l3t3|333333333333333334 444$4,444<4D4L4T4\4d4l4t4|444444444444444445 555,545<5D5L5T5\5d5l5t5|555555555555555556 666$6,646<6D6L6T6\6d6l6t6|666666666666666667 7777$7(7D7L7T7\7d7l7t7|77777777777777777888$8,848<8D8L8T8\8d8l8x8|88888888888888889 999$9,949<9D9L9T9\9d9l9t9|99999999999999999: :::$:,:4:D:L:T:\:d:l:t:|:::::::::::;;; ;;;;(;,;0;4;8;<;@;D;\;d;l;t;|;;;;;;;;;;;;;;;;< <<<$<,<4<< >>>$>,>4><>D>L>T>\>d>l>t>|>>>>>>>>>>>>>>>>>? ???$?,?4? >>>$>,>4><>D>L>T>\>d>l>t>|>>>>>>>>>>>>>>>>>? ???$?,?4?>>>>,>0>8><>D>H>P>T>\>`>h>l>t>x>>>>>>>>>>>>>>>>>>>>??? ?$?0?4?8?l>`D@0T033;(;@;X;p;t;x;|;;;;;;;;;;;;;;;;;;dub-1.19.0/bin/ssleay32.dll000066400000000000000000010060001360435400500152630ustar00rootroot00000000000000MZ@ !L!This program cannot be run in DOS mode. $G/?AlAlAl lAl lAl lAl@luAl l?Al lAl lAl lAlRichAlPELKO!  Pz-`p$ P #@.text `.rdataа@@.data1.@.rsrc@@.reloc"$ &@B3|$H% ̸ 3|$H%̸f~4  u dž F4N +ND ;}PjjV? _YFD GtPt)jVL2h(h hjjj4_Yh+h hjjj_YO ;}WNT ‰GWNT ‰GWNT ‰AdwXF4 FTV<SZPdUl ?vTjVt1hCh h(jjj\][_YjVI1h7h hjjj1_YËFD+WPVG= ;tPjjVg> ][_YËFdtNhQVUSjRjЃNT t(jV0hTh j}jjj][_YÅjPPVZu{Fl~lGVTQPSV7t(V@P)u~hh jAjjj][3_YÃtGu+jV/hrh hjjj][_YjVfSh hjijJ[hBh hjij*FD+QPVF8PjnVm9,[F4Q VTv%jV+hPh jDjij[UWhFD+WPV7 ;}PjiV9 _][ËFdtNhQVUSjRjЃNT{r;u2stJ:uv?Q:Wu v2A:Gt*jV0+h`h hjij_][_][́~4@ uZF<@NTQd vhph jDhjRhQ@PNTF4A Qd BVDFHVw8́~4` u`F<@QD vhh jDhjXRHQ@PF4a QD BVDFHV8̸0SUnT3~4p WD$ D$D$q uOFL$ Q|$\jPL$,Q=FTRPD$8PSGPL$DQT$4RQP0~PL$$WQ |$ WT$D$ @D$ D$ D$PPsL$D$T$D$B\$BT$ PL$ QRD$4PL$8Q:T$0D$(L$(T$0QD$4D$0\$(D$+F4SFDFHV$[_],ÅtQT$t Rh?hjjjdj)́~4`FS赸؃FFTU39$+Ѝ:`0L$jQT$ R@ |0|hhh8 HQPT$ R虷jD$#PL$,Q舷FTD$+PdRhPD$8PoFTQPT$DRUjD$LWPƷFT<;0L$Q]_^[ hhjDhj辶]_^3[ hhjDhj虶_^3[ ̸Vt$ WD$D$ L$ džvhhh T$ W+RV } _^Y+uFdtNhQVjT$RjQjЃ_^Y̋D$@0VhChh ׵ trh jVehKhh譵F0thOhh菵 F4u-F4t PrF0t PbVY3^ËD$PpT^̋D$uL$PǀYY̸ fVt$jjjD$PL$$QR1u'jVjJhhj|j聴3^ ËD$PQ T$ RP ujRhht t:PD$u:j\hh: ujrhjAj|j߳3^ ËUPD$訴L$iFTT-NT0vhTjdhV VG]3^ ËT$z ~h$jih# NTSW|$$ۃPD$$#ݍL$RjPQFT׃RT$8#8D$0QjRPгFT(H\vT_3[]V`^ ̃|$D$tPTRHTPTR@Tt'V1~^u ҋ@XRPPQW̸|$$SUVt$(NTWty`YLiTy\YDiPL$,T$-ȍT$RL$2D$3IPL$QRβPD$$WPSL$0UQjT$XRD$@PL$djQT$LRdD$P@P赱_^][VFTWx(;|2|$t^P)X(vT^,_^ËH0H,^PNL)X(vT^,_^Ã~`u\$ 9L$ vL$ U3u9nPt9l$u 3G9l$tNL@0nP;t*/RQP迸H,t@0WQP詸VTj, FT@(;NTQ0VL}=j<F tBL$VT+QFJ0QP英 ~:;|;~:VTj,FT+x(6hhhjpjTvT~(]_^ËNT3A,VTB(|$t^P]_F^]_^PF^̋FTH;L$P;T$t W=<Ij׋Nt FTFP RP8PRQ謰 !hhhhj芯NT;A t~!ANT)A 띋@ NTFA$_hhjhj≠ƶSVFTW3ى\$9x tD$SP_^[9xt!|$ FTU9xt;v8QدP萯;ljD$ }_^[ËR諯D$ ?v/nT}u&v3E++L$3BwFTxu 3*3ҋu3+FTxt 3ɅVTl$ZHFTxȋAXIH?VTzt@NTQHPNTQ E@D$, HS؃D$0E W\$(=u4;4VVj Ut$D tpV |2!ue_[^] ;}hhh hj ȁuED$FD$PjU c}XD$4 D$4@}(L$ D$4Elt u%T$$SQPUuEljUD$4D$ MD$4t 18@D$4v;D$2hhh4hjD$$PjU" }jjj U T$4E\WRP耪A| t'U\WRUЃ uyD$(h eM\Qr; u2st2 :uv'J:Nu vR:VtD$(h*D$D$4ljD$4p D$4u"9t$ th9hD$/hT$(L$$ ;rh@hD$2h~L$QVPUlD$4ƃ}lD$4tk~gL$xQ3F~%T$VR.9xt.D$PF!;|hxhD$/hD$48@D$4;vhhD$2h33;D$ ~ <tA;|;ωT$4|hhD$2h}|5T$$D$(L$QRPL$@QU-uhhhTUl#hhhhj:VMXAAAAjQ D$PD$PjU n9ul&}9h t$$@0lQL$T$(RQPRPhUЃT$ElD$$t$;uAUPRU蜍D$$;uhhD$(hEt;t PȞEx;t P踞PEtR謞ExMX3;thhD$PhTWQ3E~Q$VPD$;tRF;| EXL$UXuhhD$PhU3~"L$ $;t@;|;hhD$/hV9EltD$xult\PT؃3\$(~?VR+Ћ 3T$~\$ ;t-@;|\$(F;|D$39ulD$;u3 EXދ;t P蠜L$9t$uh?hD$/hUt$EPPU;hIhD$(h<3@t$(teW~LVW@ t@ tD$(WF;|օt EXD(D$(t MXDEXDEЁu=| uUEuD$PjU豫 |$}D$D$t P;D$_[^] øS\${40!UVWDCS$QRlSD$$$$jP$L$,Xt PIW̅u h hjAhjԃt PLPiLtuh 댋NQdR U$PQVҋAD$$hR|$O P;~h hD$2h[.jPWӄ u h hjhj誂t P‚Q?u h PVxAzh hjDhj?D$ @33ҩt Q|t jR胃SuQ݁D$tRSI?0t h Ou OG skGQPD$PL$L$QVT$,WRo}h hj{hj3}h hjD$uj@MXPVWj$Qjr }"h hjvhj3|hh hjzhj3|ptuHPMXRPVWjQR~h hjphj3J|#uKHUX@QVWjRP>~h hh1hj3{,t*+t"h; hjDhj{+jPt}S} @tVh@P 3L${8@I@|EXj Pj@L$HQSu}S| h5 :D$/h hh hj'{2VjUF UXx^tP }EXǀxmXeߍL$ QzT$RzD$L$x_][3襂p̸FS\$C@0VWL$QRjh!3h!SD$,|$(|$$Ѓ9|$CX@Ut9t4hj hhhjz(VjS> S;~<9t4hq hhhjy VjS ]_^ǀT[à t4h| hhhj yVjS誉 K@L$(yl$;u h hjAhjDyD$(xH  WD$(;t4h hhhj2xVjS .3Ʌw_Ux;Vh hhhj(xVjSˆ $D$(p P lD$(;wYD$ VD$,Pjx D$tnL$ 9L$(T$PRuxD$;rl$$h hhhj2wVjS h hj hjwD$t PwD$th8PyD$]_^[h |h hjA릋tt h CXxtnSwuaPVjSY nUS=QWh hhhjvVjS #t PvUxu*Ru h 8th8Ryx)]_D$D$^[Vt$~4@!u\V蜰u4NXDy uA th hjDhju3^PVJF4A!FDFHjV讞^̸&}3ĉ$SUV$~4!WpjP\7|$h* hWcu؃ L$QR\$7WD$0Pj\$8D@jWGD6;D$D$L$QW\$6WBT$$F<ŠRPutpN@<P<H<8RQPx< VDF4"FHjV裙^Vt$FXu#h hhdh2jTp^ËNA0T$RhjCh"h"VЃ|$NXu#h hhch2jo^Ã}3^ËFDSW~@S;EL;T;u8h hSo tu!h hjAh2jo_[3^SGWPMw _x[^̸vSUVW3SD$ 3C|$\$v$D$$jPooS<t$$;t|$;tD$nVV0tVF@t V薴9u)hhhhjn_^][9t F4=!D$$ut@ -h,hhhj&nVSSj RFnFXnPN4:="=="-!=w4$V^0;SFXǀP"!VF4!^DuF4~^0tVe;T$;Z`džF40!^DsV;9^lt@Ƀ !N4^D=F4@!^D.VXD@$u;@ u2V;b,%P!F4^Dl$F4P!^DFXDI #ՉpVX9pt9LusukuftNA4;tTDB t5PGmNXDJ уҁ;l$F4`!^DV7;hF4`!^Dtl9tuYFXDOttC u>G u5V;NXF4!ǁP!^DVXFXF4p!l$9x`VksJV%;NXǁP!F4!^DV;gu F4!VX9tV;8^DF4!Vu;Ёu:=|3F4!^D9yFX9xu NXF4!^D9xtVj`3 $FX|<* *tMV zdPQjP1lPVҋFX|)RjPZj؃|3V7;FXɃP!N4^Dh!h!V9 ;9^ltF4^DW@҃ !V4^D9VT;F4!^DVb;cF4P!^DFXDFHdQV҃%h!h!V ; FF4!^DHdQj"V҃F@dH,P(QRh!h!V跑;F4!9^lt$FXɃP!P^D)VXǂP^DV?;`^DF4!=0t=@t=`In$;t UjV׃ %=F 9^hhRhjbej(jVu D$N;t Wh VЃ _^][ÐeAu%Tz6X߉     ̸H3|$H%̸VkSUl$}4Et$;18F(t$,D$, D$,0@t$D$, ;|qhthD$@0lQT$RhjHQPS҃t'D$uL$,C@HRЃ;uD|$,ƍuHr;st,:vV:Wv F:G;EhuS}lr;u?st :u'vN:OuvV:Wu t$Clhh\hhjD$$/^t$ClxDvjS?u D$PqDT$,VRHP9f D$,KƉD$,QHPҋu+hh\hhjD$$/+^$FtDȁu=}+hh\hhjD$$/]SBLjjD$4S賉VP]}+hh\hhjD$$/]t I{lt<;Ft+hh\hhjD$$/7]0KXDЁu=}S]L$,A{lL$,t9;t+hh\hXhjD$$/\u]KX;D$ L$T$RPQT$8RSnhh\hhjX\Qt+hh\hWhjD$$/!\PPFNhh\hhjD$$/[S)hh\hhj[_^][ËD$L$ 9D$,h&h\jshjD$$2f[bhxh\h,hjD$$/>[:hfh\h hj[T$@B  D$FT$RjS"k _^][̸vbS\$ C@0UVL$QRjh13h0SD$0l$$l$(l$,Ѓ9l$CX@ DB t W thQh\ jrW{@ZD$;u hXh\jAhjZ@/OW  M;th`h\2h3Ʌd$7WG  DD$$;VL$0Qj|$8Y D$9t$,T$PRYL$$|$,D$;rD$PSGPshh\hhjYVjS*i hih\2hhrh\*j hxh\2hh}oYft P覵D$jPGXUD$ yXCXD @ |$tb@ t\D$WU܊3Ƀ9L$;}jhh\L$hhjWVjSh D$t WEZthh\D$hhh\jEjP~WL<t PW/~t PfWhh\jEjPFW3-~N;t PW3ɋL$D$L$QVT$RVD$h8PXD$,_^][ǀT^][̸X^3ĉ$TSUW$hG@0L$TQRj3hAh@W\$,\$D\$<\$H\$@\$8Ѓl$9\$T GX@ tkDA t6L;t PVLWX_]T[$T3]XËVw@t$8;tw@l;tP&XZlAp;tPcVXpBt;t+P2VYtձGXDHX T$VR`PPu hgh\jhj.NUS Pu hlh\jhjNUPSNO؋GXDA \$Tt)S*O=~hwh\<h6SOD$$ND$,kF;l$l$ L$TЋD$$RSVPQ-OD$)l$tH @tHHQFMD$T$$\$4RSOT$4Yt3R\$@%ND$0P\$~jSWD$~]MVBd@ j0L$4QRVЋT$@j0RAdDD$,@ˋӈXPF4^DFHjVl$_^][3BKxhh\jDhj=Cn \;uj jVCSh h\h) XpSzDu h h\jhjBU?Du&h h\jhjBUCKUQWD؃ &h h\jhjfBUzCVBdP SWQVҋSjWAJURcC‹_MWQ,CUC,Hj(jVRh h\hgXtu/@HPAD$$28&XSBSB؅QCD$u h h\jAhj?ApUPCu h h\jhjABL$QgBu h/ h\j+hj@U.B h< h\j+hj@T$jRSPW^B؃ hC h\j+hjo@FHdA SWRVЋSjWAHT$,jjjjRAPUnAha h\SH@$D$JA|$D$t_t[L$T$PSQjRRAPU$Al$0SUGWGD$8PC@U?L$FXj PS>L$PQT$\RS3?S=AD$hPjjhjU?P}#h h\hhj5>fj L$dQT$$R$P0UGD$0@}#h h\hhj=D$=r GXXP$QGWEjjjjjUH?$~FXU/?VBd@ j L$hQRVЋT$4RA=;P{>‹_WQA> t P/=P>u h h\jAhj<PV3Bxh ,h "{3D$ u#h h\hhj8<ih$Qh$RLRVЃD$=v h h\jDhj;u#h h\hhj;P$QRlL$(QD$8$$jP$KCL$4T$@ Ht Pt;LR<9Lt.9u h- h\jAhj:t P:$Rz<9uh7 뛋VJdU$RPA VЋ$AKICu+ًS$_PWB D$ $hQ:$hR:|$ Tj(jV!J %j(jVJhS h\jDhj9 D$P;D$t P9D$t P:L$$Q9̸A3ĉ$SUV$WD$(3P|$9~4vNDBt2j jUF@hqh\hhj/D$4 ][VW}@h0 3D$;u hzh\jAhj/L$(w v D$( L$(3;vI0UX`@;rEЁ=F ؋˃+ύT1;T$vJj2jUc?hh\hhj/ D$thDP<1_^D$][uNSVU& t?L$(F ؋Ӄ+;T$thh\h|j2jU>hh\hh^3vi>N DD$;WT$Rjt$$j1 9t$PD$P~.D$;rL$(UXXEX\MXltыlhDP0MXT$_t$D$^]l[ u*j2jU=hh\ho t -fj2jU=hh\j >j2jU=hh\h hk̸4UVt$3~4pWl$l$ u%;t9(t9ht F4rF4q~4qD$ PL$QVZ ;}_F^]FuV9l$ t3D$;t+PVF4qHtT$ RVu!3h4 h\jjhj3Q,D$;t PX,D$ ;t PS,;u7>u"FXj)jVX=< _^]ËNXǁXF4r~4ru1VXF4sXu3 PVIYFDnHjVT_^]̸&3UV3WUl$D$3E|$ l$2$D$ jP++U<t$ ;t|$ ;tD$ S^Vl0tVrl@t Vp9t $F4=Ut-VUUj RF +sFXFPN4$=0gI-=$TVn0g;FNF4 nD;QP+-FV;9nltF49@F4{F40oV;u!@FlF46NXD@u:@ u1Vv;H,ҁ@V4D$F4@V;VF4PnDdV;F4`V/;FXDA tV!;3VXXF42V:;\F4V+;=FXXu F4 F4FXF4Vx;NXF4nDhhVsT ;FX҃P°V4nDDFX;uNQdBVЃDNQdBjVЃ+V;F4NAdP$@ RPhhVP;FXF4 9nlt+VXPFXvN4FXhe9@tNXǁPKVXǂP9V;cF4Vb;DF4@hhV9Q ;Fl%F4F4H8=@t =Pn$;t jjV׃ F9n|tD$ @^ËL$ t A>ut @@@@`t>|A@B@>|@@^Vt$~,~4@F0u$jjVF0FX tD^ËNXtVB_^3]L$`3dÍL$QkT$jR7D$WPlL$$Q Pȃ|0tT$tRD$SP HQPT$RWD$ hxPL$$QT$HRD$0PM$L$jQPT$RFPL$ VQWT$,hRD$0PL$TQT$uOVXǂt2y u VXǂzu NXǁ_[^ Vt$FXxt PNX|t VSPVXjxFXxjj Q^̋D$ L$T$SPj3I[̋T$S\$ Ul$VW|$ WU T$>PU@ _^][̸$v|$0L$(AXUVt0P`T PUD$T$PXȃ} ^]$3Ҹ0SWL$؍D$PL$ UQT$D$ RPL$0QST$8hxRoD$u FuX|_|$utPQadVXL$ǂFXVXFXuNQ|)P-%uhQ؃3ۋT$,L$(+G WOtAVuEhh|(hjhjB_]^[ 3ۃKRQPW W|$ t/WFHdAjRVЃ } _]^[ ËL$ Ooo t_VBdjVъWD$OHD$,G|$0t _]^[ ËT$L$y VXL$,h~XT$(t~XQRl~XPVpC_]^[ ̸$3ĉD$ D$0SVt$0NX3ۉD$\$9u Vt8D$4;t tu 9\$@t4t/hh|(jDhj^[L$ 3$UWFX9`|$D\3;~/VX9`v\$VX`O3A@;ڋVX39`$VX\VXGA;`r_]^[L$ 3$9^uOV'0t?F VЃ;Wu,hh|(hhj/$ $~X n9_t ~8u a;FX9t ?UF0_9L$<n\T$L$`o+;s;v%_W (\$+GOI3;wߋT$9@V$;FX`x8\l;^9R`FX8]^8^R8_FNd;tVhRVj\PjPSуV%FX9VV(}N Vу;YVX9JVFjVj Vq9uTT$L$XsVRj_VFmP j VYP;tkV$u]FX9uR>~J`rA\u8;t.9t&ujdUV_1 IFXXTUXFd;tNhVXQVjTRjQSЃ;u;tD$9\$t Ph@VT$ XNX;.dhh|(}'hSF0ue9o9_O 99D_Fd;tVhRVUQjQSЃVXV)/`ri9^udN4u$uV$ҁV4n(F VЃ;>NX9W|r=j=__phh|(hR__n]^3[L$ 3$Vk"0t |$<u9uh h|(jdD$D;O;wW WD$URPd 9\$Hu))oGo;uF8_t V_]^[L$ 3;$h`hmh|(2ji|N0_]^3[L$ 3$Ã}NXhh|(RhFjWh(D$|)P~%ubPE؃3ۋL$+G GOt;VRu:hh|(hjhjN3ۃKf fW W|$ t(WFHdAjRVЃ  L$ Ooo t_VBdjVъWD$OT$ HGFXhVXD$tVXQPǂlVXjVpFXǀ_^][ ËNXuVjjj RFdtNhVXQVjRjQjЃut"FX Rh@Vу _^][ ̸UVt$(FXFdVl$,ǀd\0t@~u:F VЃu'hPh|(hhj^]ËL$4+SL$W;v|$L$^XL$8;l$ D$\$(uV{ tT$4WURVFXtNQ|)P;%uuP؃3ۋT$L$ +G WOtNVuRhh|(hjhjPNXT$0_[^d]3ۃKRQPO O|$t$OVBdPjQV҃ |D$Goo t_NQdjVЊOD$,WL$@:Et6h h(3hhjWjV& _][3^Á~ uH@~h(hh( FXSQP}VX _][^Ã@~h(hh(H FXSQP5VX _][^̋D$H4;L$uP+$+0ø*ø3ø-ø,øPø(ø+ø.Ê+++++++++Vhh(j j 39t$t`\t;uHt@Puhh(j j Ruhh(S ^Ë^Vhh(j j |$t`\t);tuH;XsrP8@p3hh(j j t V+^SVt$ V =tVt =u FXuy CAtǀ@uWju_u hh(jAhjU^3[ËNXVXFXNL^[SVt$ V =tV =uFXup\ Suu\ SWj_u h*h(jAh#j^3[ËNXVX^[Vt$Veu^V&^Vt$FXt-SWjNX_ǁ[^Vt$FXt-SWjDNX_ǁ[^̋D$u=u!=u=u=u3̸(̋D$u"=u&d=u =u=u3̸$v3ĉD$ SUVW|$8334"WLj WI؃\$ wLD$$NL$(fVfT$,F D$.~Fu~u<k4<,~rfF<ruG4"<ruG4"uG4"uG4"<~~Fu~r ~ u~rX~ vF |z|u|uuujVh*Ӄ tXjVh)Ӄ tGjVh)Ӄ t6jVh)Ӄ t%jVh)Ӄ u(hh)hhh)h\$4"OLQI =D$T$ D$~hh)hPWQWPGLRPWGd tOhWPQOLWRQjjjЃoLU]ME E U ‹W*D$?T$@D$AD$BD$C t$ t$T|$$t*EEEEtEEECXǀt|tm‹QT$RL$$QS҃uJD$++PT$E3EtȃPMERU.CX l$ǀ+ǃu^]_[L$438Ë^GL$@]_[38̸覦D$T$ SUV03W|$$OXD$D$D$,ЍJT$;{ffNff ;tL$42_^]3[ÍB;$Nff Nff .L$0D$;tRUVQjWЋL$Hfu# fD$uf ?_MF;ǂt Phh /Sם SVP+ f#uV`tdQUVWЃwjjj W@qf|$0eLJ@yfu1?g(KfBLJ,Bt3f;GX$3v 0ɍD;r;RUVD$0PL$Ht P踙hh /j誙 Hu#hh /jAhjI_^][džDH@HAPt PChh /j2džL2+ PuLhv3ҋPAdr_^][Vt$FXD@ u @@trHt P虘hh /j苘 Hu hh /jAhj*^džDHBH@^̸膟Vt$ WD$pt upttPT$ RVы (t0t&<t@PVуtCt/u dž,ǃtRt6uX$_^YÿD$P398,뾋T$RjV5 _^YËD$PjV _^Y̸vVt$ HD$ptzDvqtavWFXD@ u@@tB3vAt3@;rhh /hhjO^YËW3t upttPT$ RVы (ty,uptf<t]8tPdž8dž<@<QV҃u D$q } D$Pǃ_t.tu4$^YËD$PjV舥 ^YËL$QjVr ^Y̸Ɯ3ĉ$$SUV$0ڋpW$D$ L$$D$y$RMD$,P諕8t7j$QT$0ROQWSЃ-utD$j׹+Ѝd$;sjÖPjR$P視OQ(Uj蝖PT$8R$PؔD$}L$(QI+V$WR'j$P$Q $RD$0 >$rU;0st-:UvQ:Uv A:EL$(Q谕T8D$,PT$ 螕+hh /V]T$(uR`D$VPL$QWR轖L$$D$(PQT$DR衖 ~oD$D$L$(QT$RD$ Pj|$(]Wےt4$tL$ WQVHRP D$$~D039D$ ђ$_^][34ĸ̋L$ 39 <t @rË@D$Hw%$Df˒邔͕Z齕鲕3Ð"f'f,f1f6f;f̸VD$Sȁu=}[YV3;u^3[YËD$;ƉsPsDs8st~qUl$HE@WD$EUT$tt u:p v|8|8uL$Qt uC8l$u_3]9sPuؔCP9sDuoCDgC89stu谔Ct^[YøVSUVt$NXWf8X@x ߍxFdl$|$tnhUVQRjRjЋl$4fh Ch /PD$$zL$}ES_QWjW\$8SUjV0|FdtVhRVSUjQjЃU}:_^][Yfu,u'O ;u@dž_^]3[YW|$ t#h h /hnh;jQ_W0SVh h /j%TCCsNjVjVj%SjWó,|%GdtWhRWj%SjQjЃLJSՎ^[_h h /hh;j{_h h /hmh;jX_øD$T$ SUVt$ NXW83$dž(L$,D$D$XD$;9ffoff +˃;H;d$Off Off ˃9\$$L$,;tT$,QRWQjVЋL$DffW ƒ;D$,\$$ZGfCfKCff L$,;L$,$9Vlf;4hUh /RɌ USP.) P@u+;dž$Gt/HL$@u+D$;uUSR u3$D$,+ŃD$,T$4_^]23[f fvfI;u΃hCh /P請 SSOQP P@u+;JL$42_^]3[f > Io;~ltP ǁh!h /Sǂ܊ SUP0 zf >dWڃ;n~lChEh /Sǀ4 %SWRQ腑 f#u.`dL$,RQWVЃf;u)L$4T$,QRWV25D$hf u]|$xfnOT$ \$$;PWV7 f><f;(\$$;D/W ;LO +й+مKPT$4R|$8j- D$$;|$00u^0D$$0PQ9bf/W \$$;|$04thP轉UL$4Qji 46;l$0*rdž(ffu +t+H @t3f;uFXu*"fuL$4T$,QRWVMD$$D$H; D$(8|$2%L$4hHh /hRh.j(y_^]3[ËT$4_^]p3[ËD$4_^]P3[ËRhL$8_^ǀ]p3[_^][ËT$$RD$4_^]23[ËL$$QʼnT$4_^]P3[ËD$$P褉L$4_^]P3[ËT$4_^]/3[_^][̋L$D$ S\$Ul$Vjjj S4(ǃ@@t^]3[Ë=~L$t;r^][=t=u t;sffF ЍD;sD;w;sPW;wFpff pff ;wf#tƍP;v_^]3[fu_^]ǃ@[ÃhuNL$QL$(URPt&tt_^][ǃ@_^][ǃ@_^][̋D$ u3Pa39 t Ar3ËtԋD$Prt‹L$A̸&3ĉ$$SU$W$D$0$L$8$VT$@D$0L$D$8؃}h@/hh0/ك T$RTD$HPJL$jQT$TjR $PWjhW(WjVL$ jQWjVT$PjR襆t$PL$UQ跂 D$0t$RPD$P葂 kD$8t$QPT$Rk ED$t FX3ɃHFXHL$A$tN|f|9t D$;hh0/h| ;uh=h0/jA9P|UPT$D$@;tP~;t OQ~;u h>t FX3ɃTHFXP`T$\D$ 9l$t D$Ps}FXxT$L$ RD$m{t?NXDz t JIɃ;|tzO\$S~%uX SE{؋$ t1!t,D$ (G(T$$;D$0|/D$4'D$(xT$$XD$0h/D$4VX;t~hh0/jDD$PQL$$QȁT$$R~ u=D$ T$D$,QRjP}L$LT$HPjQjRD$P}D$PPy(|$(T$NXRL$,zT$(P$PD$0$QWRT$Djjjjj Qj PjRVnP@tY$~lFX QT$dRL$HQjh//jjjjj Rj Pjh\/VRnPY@u3|$4tl$@ l@|$$t$V@|%$ u#PjW|$ jVW{USjW|(L$PUWjVQ{|$,Vv| tT$ tL$QPjWN|$j@Rx$j@PxL$Pj QxT$xj Rx $_^][3̸fU3Vt$ FXl$ l$l$9tt ^E]ÍL$QT$ RD$PL$ QT$0RPyu&hUh0/hhjWw^3]ËNXT$ |FXL$VXD$ NXT$SD$$WP~wL$,Qw\$Vthbh0/Ww؃;u'hdh0/jAhjvD$,_[^]ËVXhktFXh0/Wxv uhmh0/jAhjmvuWUSV_teuPV:EFX3;t*x u FXxu FXL$tWUvUv D$_[^]̸8f}3ĉD$4SU3VW|$L\$$9\$PPvt0QvPJv}h/hh0/)v wX0l$;u \$ Ux?؉\$ S?y%SuN9N t'hh0/h/@PPQtu_^][L$43|8ËRut0PuPLu}h/hh0/+u wX l$;u\$ Uw؉D$ VNFM^Q\$cwURD$x T$PGXtTt.t&L$(PT$,$ufy_O\t  |$PT$8t  fPl$L$9HL$:D$8fT$>L$pL$VQKsD$WX| QT$,R8rD$,PL$4VQoD$8;tD$D$T$RD$PEU o[T$j L$@QHRQ$PjjjjjjT$t+V‹T$LPQRWcP@uD$ D$$P?nD$$_^]3̃ u̸<u3ĉD$8|$HD$DSUVt$LD$F|WtD$FX0TD$FX WD$nPIn}h/hh0/&n l$ L$8T$9D$:K|$L$;ST$;9us :t* L/d$>;9u6s:u"hh0/hoh:ji3JL$$QL$QL$(QHQJXDPD$$jjjjjjjjPB$UP@|$t Wbit UUi_^][̋D$sX$܏3ø øøøøø(ø*ø+ø,ø-ø.ø/ø0ø1ø2ø3ø<øFøGøPøZødønøoøpøqørøsÃË+.4:@FL֏RX^djpv|ďʏЏ֏ 3|$H%/̸/3|$H%`0Vt$~4 !u-Fh;h0h3 %u ;uGm$;t,A ЀɁQPWՋ ;uhOh0hWX9Ht&SchVh0jDh j[bVc;u h\h0jh j,bGXHF;t99^t4u(PcENQwcE9]t;uhsUUcuhh눋]U E\$0T$4D$8E(;uEm,;t*A ȀҁRPWՃ ;uhh0h7OXL;tQZbh;u hh0j+h j aPb;u hh0j+h j`sWXVLNbtV;bt t-Vbu hh0j+h j`Va؃yVahVaWGXDA t3Sa=~#hh0h6h j`SfaP*D$u#hh0h;h j_fjjjjVBaPSahh0U_$D$(`|$(D$$tztvЋD$(RUPjV`PS`t$@u hh0j+h jW_L$$Q`33ۉl$$t$\$0l$4l$8l$j$QT$$R$Q$RVЃSUa$jPU$Q(RjWPD$,P>VjWPjQ$RW$ $$$D$D$@D$D$@D$D$@D$D$$xD$$|D$PT$$JL$$T$A D$RVL$P$PQ\T$,RVL$$USD$0PQL$4L$@QVD$8D$ PHRSN \$E\v hHE\QPCScNU\ jCPU?rPUetuhSh\1h Ctu3 P&F؊F3v WREGF;r|$@QFVUj u&hih\1jDhjE_^][Ë+D$PjPjWU8Sj+UE4uDEHB jUH_^][̸MF $QRjh'D$@0h&VЃ<$NX@tV\FXǀTYËSW~@;uY8GuT_v/PjVU _[YËF\SGWPLN\ V\_[Yhh\1h hjDG FPjVT _[Y̸K3ĉ$SU3V$~4Wl$l$l$$l$ gF~jSWD$~]MVBd@ j0L$4QRVЋT$@j0RACD$,SjSjPVVPj VF4^DFH @ jVE$_^][3pJhh\1jDhjkB Yp;SCu hh\1jhjBUCuhыSURWC؃ h붋FHdA SWRVЋSjWAIURB‹_MWQBUB,j(jVQhh\1hhhtu1@HPkAD$38'@UoBU\$uBD$Bl$u hh\1jAhj@cSUBu hh\1jhj@5UAu h1h\1j+hjh@SA h>h\1j+hj;@L$jUQPWA؃ hEh\1j+hj?VBdP SWQVҋSjWAGjjjjU(AT$$PR@hch\1S?$l$$@D$ t[tWPD$SUjP@L$$PQ@SUGWGT$DRC@Uu?D$@PI@L$LQO?4Lhhh\1jAhj ?h {hqg3D$u#hh\1hhj>Uh$RhL$lQLQVЃD$=v hh\1jDhj`>u#hh\1hhj9>vP$lRPL$Q$$jQD$@$EL$(T$@ Ht P=LRk?9Lt.9u hh\1jAhjf=t P~=T$`R>9uh랋VJdU$RPA VЋ\$pAKCu+ًSD$d_PWD D$L$`hQf=$hRT=|$j(jVL %j(jVLhh\1jDhj[< L$ Q=D$(t Ps<D$t P@=T$RC<x̸0C3ĉD$,SVt$<~4WD$\Fuh-h\1j L$ O T$ W N=CPL$QKWRjD$4PQ=uh>h\1j*mT$ W D$ G \$ SjSjWV2Hj V^DFH7 F4jV=_^[L$,3PB0hGh\1jDhjN:L$L_^[3̃ B0̸AUVt$3~4pWl$l$ u%;t9(t9ht F4rF4q~4qD$ PL$QVZ ;}_F^]FuV9l$ t3D$;t+PVF4qHtT$ RVu!3hh\1jjhj3Q9D$;t PX9D$ ;t PS9;u7>u"FXj)jVX=I _^]ËNXǁXF4r~4ru8VXF4sXu3 PVIUVFDnH 6jV;_^]̸&@UV3WUl$D$3E|$ l$?$D$ jP88U<t$ ;t|$ ;tD$ S^Vy0tVry@t V}9tV1 F4=D$$Qt[-%VUUj RF 8FX^PN4=0-=$Vn0?V V ;F\9(tNXF4ǁP F4 FNnD;(QP:FVs;7Vlҁ&V4nD#; V F\Ƀ0N4nDVm;u!@҃^lV4nDwFXD@u=@ u4V,;,Ɂ@N4nD+\$F4@nDVE;9VF4PnDV;F4`nDV;V FXX҃€PFXnDPN4wV V;F4nDOV| V;jFX9XuF4nDF4nDV4 V;"VXF4nD9nlu V hhV> ;FXF4nDDFX;uNQdBVЃ}NQdBjVЃdjV#9nlu VK NAdP$@ RPhhVJC;FXF4 9nlt*VXPFXt>N4FXhnD9@tNXǁPnDVXǂPnD|VY;F4nDZV;{F4@nD8F\hhV] ;FVNlɁN4nDF4X8=@t =Pn$;t SjV׃ %=t =F9n3 ~$t V\ǂjjj Vwt F\L$XV\8F\@N\D$DV\HN\T$_]P[V7 %%^̋D$PFtxu3Vt$F\3ɉHHF\HF\fV\Rjj-V5KP*V)^Vt$F\F\v!jjj/V SP*N\XV\ ^v"hh1h8h<j)3Vt$jh j V|vF\VǀT)~ L$ Qjj.VsJP*^ø 1VW|$G\uu fw\T$RL$D$ iNG\G\Pjj-WIP)_^ ̸ v0Vt$F\uu3^ ÍD$PT$ N\it$;|Ou9~EWD$8)0H)PP_y I@BP8u x:}3ɉH^ ËD$3ɉH^ ̸/L$ $PQ(t<$|$ 3̸v/Vt$D$PVt|$|$~3^ËF\fffF\fhh1hhj][_^YRQP!< @|$t54D$NQdJjPVу } ][_^YËT$4D$@<tPU|D$ 4NQdjVЋN\ F\ KFXPVSVf@fC5K4S\$$4 0FXTP4D$0L$,LJVXhVXtVXPQlVXSVp&][_^YSًC\8VQC\f4f;8QtwC\84RztVFPXVT Tt[KXS\(Q<RC\8Q> uC\ff<[\ff@f4^[^3[SUVW|$oX3 G\<@P؃t,SKQS _^][ÉUWP9_8u P WXjPj W!3;~ƒP uċwL_8MFFNF^ FF ÉE^GX f^fXF^ ÉE9 u ;S3E}@E8OP] ;v jSSW9!3҃;;t 3ҋG\G8]T$;u (A;Mt D$;9Tt }u>tW4u EGP39U|$tCWJW0ut G\TuUR4P3EGP=EGP#̸P3ĉD$LS\$`W|$\GX\$D$u WKt9D$`t tu |$lt4t/hh1jDhj_[L$L3PËL$hP3ۃ;$9_u4W=V0t$O Wу;uhh1hUVwX 4Gu79^u2W\PP;tUMQU{ WZ9^t 8u2Wo;%PW;y^]_[L$L3PËWX9t+>t&O\FPLQF30G0hl$h;yu)HG\D$9NsrG8^uHG\ЃtbWXWǂ4GjVj Vk3;vV^ (FN@;r3ۋD$9_$G\ 8;9G\8h8\8POd;tWhRWjPjPSуWSGX9WG(WO Wу;ekWX9\WG2G\9Gd;tOhQWRW\RjQSЃ;tD$;tD$D$;t Qh@WЃ 0WX;O0^]_3[L$L3PG0D$iN PQs?u9n9^|N 9p^Gd;tWhRWjQjQSЃG\9 WXWǂjW?G\f( 9_N D$ PQW\9Ft^|$ u"WPWC#^[O4u*WXu"G$%G4G(O Wу;hh1hhj~|*?{^^^]G_3[L$L3PWP0tu9uhch1jd5D$p;LN;wF FL$UPQ 9\$tu)nFn;u G8^^]_[L$L3PWJj^WGe/Pj WQ/Phhh1hhj;hh1jihjj}GXh}h1QhGj Vh(T$hjR[D$pPh(UE o0QR腂8^]_3[L$L3wPhh1/hG^^]_3[L$L3?Phh1jghj= OX9t=9t5G4t=|= ~ t= !=!|DhGh*h1jDh!h1h hj VjW ^]L$T_[3}PVt$VN0t8~u2F VЃ|gu#hgh1hh jK ^ËD$=@~#hnh1hNh j ^ËL$T$ PQRVt^SUVWhh1j433  t[thh1W  t5u,9\$tHhh1W ؃ ut V U _^]3[WjSA _^]0][̋F,t Py F0t Pi V` Y̋F NW~;v%hh1hh j /_;D$vhӋC\uqKF,t P'F0t PV_^]3[L$3 ËO\HPRL$ _^][3̸ S\$C\HVQtJW~G,t PG0t PW}VyS\HPp u_^[̡Vt$ j,jVD$PH H@ щVfPfHff fVPH H щV PH@  Ѓ V^̋D$L$k̸SUVt$NXXh@Wfx ݍhFdl$tnhUVQRjRjЋl$4fhCh1PD$ L$$}ES_QW{jW\$0SUjV0|FdtVhRVSUjQjЃU}A_^][Yfu3u.UE ;uVdž_^]3[YW|$ t#hh1hnh1j_WC?0SVhh1j%CCsNjVojVdj%SjW,|.GdtWhRWj%SjQjЃWLJSL^[_hh1hh1j_hh1hmh1j_̸VSUVt$F\X3W; SSj VMISSj(Ve%PV\XF\X; sYXV\X;u3I; @rXV\XSPj*V$PN\9Xsh3h h1 9^Hu/|$u(F\` 9NDth`3hh1c ;t#PPPl$R\$닆;t*RutQ|$\$~Du3_^][YËl$|$jjj V#PЋF\X+++ƒ  ,jjj V#P[~N\X++Ń ~D;~|$FHt, h83h8h1L FHFD w F\h\WPN\F<@FH\b\PQPQ@PQ PQPQPQ PQ PQQPIH sh3hFh1 Vtq\bPaP`@PePdPXXXbaP`H  MQPV FD;t'nH+ʼnFD\+~Db_^]3[Y_^][YËFdt"VhNHNDRVFDu'N\f&N\%N\$PFDF\3҉VH$jVƀ\`fdhlVD$F4jV$^̸,f3ĉD$(3S\$8D$ D$Vt$8V\W|$HL$$D$*\$+HQPu6Qh3@P _^3[L$(3.,x_WG,N<ۃU RQPRGÉFDoOWF\fd\`ǀhl\D$(F\f L$ ǀT$$WGF\L$,O W$fO(f W(M ;u&FXHTPXL$0N\T$4*PT.HX39WTRVbL$ T$$D$D$D$(N\f W(;]u)FXPTN\*@XT$0.FXL$,HTPXF\jjj VǀPL$DD$_^[3f,̋D$Vt$u$H\Tuf&f$H\f&@\$T$\T$fdL$h`lD$ ^W|$GXTtxǀTD$|BOX9@t7hh1hhjj jWT$< _ËD$OGIHAT$ R+AjPV|$ uD$PuǸ^Yh3@P^Y̸|$ SUVWl$PtQP|}uX0u3SV ;Vt'hh4h/@PP~x QVPR __^][YËt$P?tQ,P|NjvX u3 STl$ld\~Rl$tI|$tIǙD$+Qt @XtB,9;} ~8@;|Nl$|$u3ҋNV WQRS*|$F T8\$T$BtP[X/+؉\$ I\$;usD$u L$AXD$HXtJN*;d+;}^ ;\$E@;|n n++_N^][YËNVF QRPN N_^][Ỹ=UVWt4-x@u+;uD$SPRՃ t>u_^]ËL$_1^3]̸vUV'u%hhT4hjh5j^E]YSWj:Vt+ƍPI@u+L$QV*u%T$RUtw묋D$_[(^3]YhhT4hlh5j#_[^]Y̋D$L$P̋D$L$|P̋L$t|ut u3̋D$̋D$SUVt"|utt3UOt$؅u%hhT4hbh3j+^]C[ÍH;L$~'hhT4hkh3j^][ÊWV3~WUHPVG;|_L$D^]3[Ul$}/h>hT4hah6j{D$(2]Vt$NW> ׃yJBt1hJhT4hah6j#D$0_^2]ÍO;}1hRhT4hah6jT$0_^2]S)؅tI$N =t9At 9u QSuM;t2hphT4h`h6j]D$4[_^2]ËL$QlVt$$3"~o It$UVS3 ~$d$VSP;Wt"SF;|D$PE;|L$T$ t S[_^3]̋D$|$}$hhT4hkh4jrËL$u$hhT4hqh4jA@RQP@D$ 3̃|$ t.hhT4hah7jD$$2ËD$P ʃthHS ـxt/hhT4h`h7j~T$(/[Ul$ WUu/hhT4hgh7j:D$02G_][VW3~#VW9Xt@WF;|hhT4hah7jT$4^_]2[ËL$ ^_]3[̋L$D$94t4RPRPQotP_~h h4hhjC3̋D$ v!hh4hhj 3ËL$PD$ PQ ̋D$ v!hh4hhj3ËL$PD$ PQf hh4j j 1D$L$hh4j j  hh4jj D$L$hh4jj ̸3ĉ$$V$W$ v_3^$3ËVPT$XRL$t$Xy |$u$s+PL4TjQj D$Lhh4j j HT$RQhh4j j$$(3_^3̋L$T$̋L$QpT$dL$T$W̋L$QpT$:L$T$-̋L$QpT$SVt$ FtN;u I$N@$F \$t ;t PFt!W|$;t9F t P~_^ ^[ËT$^ V^[̋D$@ ̸D$@ hPD$xt $QjjiPa$Y̸VD$@hPD$(t $QjjiP$YVW3Pu hh4jhj@_^ËD$PjjhVL$VVQ_^S\$ UVt$F 3Wt:P=u*F UUjiPh;uF PPV< _^E][TP"u"hh4jhj_^][SjjhWN WQV_^][S\$ UVt$F3Wt:P=u*FUUjiP;uFPPV _^E][Pru"hh4jhj_^][SjjhWbNQWV5_^][̋L$IX3t)D$ V;vƋT$ P4QRL ^̋L$IX3t)D$ V8;vƋT$ PQR ^̋D$̋D$HpL$D$̋D$L$̋D$̋L$D$L$ t̋L$QpT$JD$L$A`̋D$@`̋D$HD$QPD$Vtt u3^hEh4jFjPJ^̋D$tt t3VW|$Wd@t$PVCF ;Gt@ VЋGFHVуSt*hnh4j jP džt SJ6[ v!hh4hhjP_^PǠWƠV _^̋L$tPtF8t?xu!hh4hhj3ËHQR|h~h4hhj3̋L$uhh4jChj3Ëu!hh4hhjU3Ë8u!hh4hhj-3Ãxu!hh4hhj3ËHQR̋D$HQ`̋D$x u"hh4hhj@0t @3ËHD$A̋D$x u"hh4hhj[@0t3ËHD$A̋D$x u"hh4hhj ùH0t%hh4hhjHËHD$A ̋D$uH(HD$Q(̋D$u ǀ@(HD$Q(̋L$39ËL$tD$PVt$VQPBlЃ ^ËL$ T$Jd̋D$@̋L$A>v0#$"L$ËL$T$ ËD$L$ËT$ËL$T$ ËL$T$ AQËD$@ËL$T$ A Q ËD$@ ËL$QR ËD$@4ËL$A<ËT$B8ËD$@@ËL$AHËT$BDËD$@XËL$A\ËT$BLËD$@PËL$ATËD$T$ ËL$ D$!ËD$T$ ËL$ D$!ËD$ >wL$3ËD$Vt$Vt$VQPBDЃ^Ð^!!!!!!!!" """!")"U">!I!!!!!r!}!">"j"" ̋L$tD$Vt$VQPBpЃ ^ËL$ T$̋D$T$A+Bu3ɅL ̋L$tAtut@u3̋L$tAxut@u3̋D$uVptut1@t*t$VL$;~QVt@^3^ËD$PD$HQPRP`t+P^u!h h4hh jH3ø̋D$PD$HxQPtRQ1`t+Pu!h2h4hhj3ø̋D$U|$SVW|$U3~MSUuPƒp@u+ƍH;L$6 BFu+T$:UGC<;|D$G_^[]ËD$;tO_^[]3]S\$ u3[UVt$St$3W|$US@tсu;|3@ u@t tL$ VPtOQL҃SEl;|;t$t6u-D$ VhtЃ_+D$^][ËGHLу_+D$^][SUl$ EX3W;tEHLSSыD$ t$hh4hhj_]3[Vt$ ;t;tPD$o D$9\$~jt$EXt/u>u%|7u|7uuQǀ$UBHVЃtL$PQtI;\$|t$ tD$D$^_][hh4hYhjj(jU- hh4jAhjD$ t8u T$R^_]3[̃|$t3ËD$t uË ̋D$t u t3Ã̋L$SU3VW9l$ D$(t$d$3vo.$:uLLt.r;u2ste:uvZY:^u vMA:FtEL$$t$|D$(;r.l*;l$ yt$Q T$_^] [ËD$t$ (Q T$_^] [̋L$tT$u D$ xT$ ̋D$L$T$ ̋D$L$T$ ̋D$8}ËHQdR4D$̋D$V;t^ËND;HDuHWPHr;ustD:+u1v5Fz+u v$Fz+uvFJ+_^_3^̋L$AKQJ QIIH  ̋D$L$P2̋GtV0Pƅu^WYVt$Phoh4j F`jP.t P[~t jV?QVj2F t PF t PFt P Ft Pt P'thDP-th8Pdžt PLt PVt PQW\t`t}V_^̋D$L$Al̋D$L$Ap̋D$L$T$ HdPh̋D$L$T$ ̋L$T$̸<vS3Ul$H\$8\$@;D$LH EVW;u9]u 3ɉL${ ω|$9]u;tP;~\$$|$$E ;u 9]$u3ɉL$,ω|$,9]$u;tP:;~\$(|$(9](u \$D9],t|$D9]0E4;t~P|$#;Ɖ|$ ~\$ 9]tRL$DQT$PRP|$<@tHD$@WЍwctu L$P 9t$ L$ T$=u |$P 9t$ |$ T$|$8t |$|$DD$PL$_^t ɀ ED$ ˀ ] MEE][<ø SVt$FXD$ D$D@ HX WL$t4T$RVVvt$ |$jjWvG t 8tPSL$QT$RP=Ã@u G(t-G,u'hh4h=hj#_^3[ ËL$ t2Ёu=}thh4hC t7Ёu=}tthh4hBrD$@t G(tG,uhh4h>K_^[ Vt$FXDWQWdVXDH @`u@tD@ _^tD@ _^tD@ _^ètD@ _^èt39G0D@ _^è uGtD@ _^étD@ _^h) h4jDhj_3^̋D$@L$t&yLt T$ t V4@t82^@D4èty@tԃy4t3ʨ@t ypthI h4jDhj3UVt$ }DpSX W#|$tq~lukuUP27tUpx(tIh_ h4jjQpJ(PVуuR*xTF$ FL$A`ËL$T$ A`Q`ËD$L$AhËD$T$ ËL$ D$!ËD$T$ ËL$ D$!ËT$ËL$T$ ]T$ ;}3ËL$=t=uA\XËD$ >wˋT$ËD$@XtËD$PVt$Vt$VQPB@Ѓ^EE&EREDE~EEEE;EgEF    S\$VW33;u$hh4hhjV_^3[8 }/hh4h hj)hPh4jA@hh4h= ;hWVȸ~ F FP~~C`j,N4WQF$~(~,~0茸F`~d~hdž;6h+h*~l~p~t~x~|kF; RF ;;4t4PVR^SP=;Sԯ;h5蔲;uhh4hh5i;uhh4hh5>;uhh4hl薯;QVjAIj@R~*jP肯~(jQm V<@LPTBh%h4j džX 裮`;tA8`h+z`h4j xq \;u`QRhPh4jA68\z\x_^[hh4hhjɭ;t V_^3[Ul$ ~3]t%3=] Vt$ W~u0~ jW臱uNjWxu'jWiuH~uj~jWQt _^]jW9t _^]jW!t(W.u _^]Ã_^]ø9Ft.u%>u _^]F0tVXt_^]Vt$~ Wu$h h4hhjd_^ËFH,VуF4pt V V҃_^Vt$FW3F$~0F4`HVN (;t PŮ;t P謮_^Vt$FW3~$~0F4PHVN ;t Pi;t PP_^SVW|$P3ۃ;u_^3[ËONGFU9t WV,dP VҋGF@VЃ9t0;t PQ ;RPV G`F`OdNdWhVh;tWpR PFpPQRj}<G ;tN QSj P萪G;t%;G tVRSj PlF FONWVG F O$N$G(F(O,N,W0V0G4F4O8N8Np^DWlVlGpPQ蟮Gt;tPaFt;tGx;tPJFx;th;tiW0;tOW~GSWU]PSWOtWC;|]_^[UV3]_^[Vt$t P艫L$ tjQP֨ ^Vt$~ u V?FHVу^Vt$~ u VoFHVу^yVhh@5j j豫,}ihh@5j j蒫hh@5j j  , }jjjh(5j,hh@5j j E,hh@5j j),Vhh@5h臧 uhh@5jAhj*3^hjVF0 džFP腩FD}F8˪Ft^Vhh@5h uhh@5jAhj誦3^WhjVu|$+σ0*D @GFONW V GFONG tPԧWVGFG twP貧F uhh@5jO At!P聧uhh@5jbV BG @t!PVuhh@5j7N AW$V$G(PF(h h@5jhjxFt PF t PrF(t P\4Ft PHt PE u_3^ËG,SF,3ۍD[  8thh@5j 0jQ[L84tOh h@5j L04jQĤwS$Sh<h@5hhj聤CldžOFPFDF81[Ft_^âSS\$hoh@5j jPlCt P触C t PC(t PVWs4Ft Pӣt PУ uSѣ_^[Vt$uhh@5jChjo3^Ã>u*uhh@5jAhj@3^ø^Vhh@5j|Z uhh@5jAhj3^j|jV̪F F Fx^W|$hh@5jGxjP辢wth8PΤSVw $t P茢 uGl^[t P Gpt PdGtt PNWg_̋D$L$A̸薩W$WԡVjW躡$WPH QT$R]u&h h@5j hj萡^3_ĈVlPD$P ~$`5uT5PL$ QɦVpRD$ P貦P蹥tPL$ Q苦HdtPhRD$ Pу L$Q蟤T$lD$P耤^_Ĉ3_ĈSVW|$W3螠~3IVW臠P t"PS٠tWFk;|_^[hDS虢_^3[Vt$thDPpD$^ËL$ ^Vt$thDP0D$^ËL$ ^̋D$̋L$yu%=uIXtl3Ëu Vt>?u 蹟t.VդP蟤tVP菟u VR3^ø^ËL$W|$_̋L$W|$Ǡ|_̸vSUVWh0D$3EP D$PjjlUWWL$QUu 軞taT$RӣtkP薣t\VSV| KSpVWijjD$PU苣u/hh@5jAhjthDW 3t S蝝t U辟D$t P軝t_^][Yhh@5jAhjw̸S\$UVWh0SD$D$ˢP裠 uShh@5jAhj3t WD$t PL$QS萝_^][ËD$ PjjlWVtjjL$QW>t\T$R'tPxVSlV| 蛟 SjjD$PWu躜8̸ ֣3ĉ$S$U$VWh,h@53jj t$ t$$譟D$ SP舡;IˍqAu+΋ȍyAu+ύL1PSh5T$$hR,=D$PU L$SQz8tihHh@5Pj j5h5Shl5j譞hJh@5jhj 8(h7h@5hhjD$|$_^][t $R^hRh@5jj h$D$3腢 ̋D$Vhh5jj D$thh5jj ^̋D$L$T$ PD$ QL$ RPQj̋T$T$̋L$L$VWhh5h3 ;u hh5jAhj臙_3^hWVSWdž0PVj._^̋L$D$tPDH̋D$S\$ Ul$ VW|$3PS諘~QSU脷 t F r_^]3[à s_^][Vt$>hh5jjP[QVjVjRޘFj0PӘNHj QȘ$t P+t Pt P豗t Pt Pdžt Pȗdžt P諗t P蘗t P腗t PrhVV^ ^Vt$W|$A\RЃu5NA\RЃu#hh5hhjʖ_3^;FtPVth3h5jjQ觖t P_^ËtPdž;FtPV4b_^̋D$uËL$̋D$uËËD$uËËL$u3ËD$̋D$ v!hrh5hh8j蜕3ËL$PAhD$ PlQL ̋L$u3ËT$A$Q$̋D$uË@$̋D$uËL$T$ hl̋D$uËL$T$ `dVt$>\tPdž\W|$hGh5P֔ \u hh5jAh&ju_3^ËL$t+f8\PP\WQHQ _^3f\_P^3^ËD$t{tqVw;u%W;u?/w;uǀǀ^̃Wtt VUOGuO01_É0_̋D$L$A(̋D$@(̋D$L$A,̋D$L$̋D$̋D$L$At̋D$@tVt$ V[uhmh5j&h"j薒3^V)u(hrh5hKh"jgV#3^ËD$^̋D$L$Ax̋D$L$A|̋D$L$ T$PD$QRPh5hp詗̋D$L$ T$PD$QRPh5hp̋D$L$jjjjjPQh5h0U$̋D$L$jjjjjPQh5h0+$̸SUV`_3;u^]3[YW|$p@$;u WB;tP9\$mu FDK=u9=u.=u#=u=u =FD 9@t^DhZh5j j*;up;th_h5j jVDD$ P^HSWT$,Ճuhfh5h-L$_FD;Ts?u+PL1HjQɗ NDVDRSWƮ th~h5h.L3ۋ ;tPk;u h9Htj;t P谏Dhh5P蝏 ;uhh5jADDHRQP 9P;t P:Lhh5R' ;uhh5jAaLLPRQP| %hph5h/+hMh5h^D v)hh5jDhjcV_^]3[YPRFlP Nh_^][YU3W9nD9l$ thh5j j 蔑GSVP@؃;uOVQ~V |$thh5j j It!ǃG,tSWЃS[_]_3]SًCt;~:SWVR;VdžC, _tVSЃV[̋L$Vt$^ø 膔D$$@D$t\D$Vhh5j j D$lD$p L$Q@ T$ h kR`D$(hh5j j p 0,^ SUVt$Whh5jUP\hh5j j |$8OVQ؃,t;tSS3ۋttS3jjj+Wjjj+WʹjjjW迴 ;~qwtj~DtdWVR;uSGVPTVhG, tSWЃSoTjjj+W\jjjWN$;hh5j j _^][̋L$Vt$ j^W|$tEG0u?Wf0u/WV@uVj^_3_̸ 63ĉ$$SU$V$$3Ƀ W$ L$L$\$;uL$L$QPVUW@w!$q\$L$9D$X|$GL$GpB D$t$`VL$hUQ芑hh5j j_pHT$8RQ$D$thh5jSP膉hh5j jL$ pXLL$px0p$RV$@0UWЃD$JpX\$t L$hh5jSQp@ uT$RPGL$Ah;ilr'$];st6:]n;v"^:]Yv F:EHt/u+h>h5hhjL$$\$$$$$%=|OAH$RЋL$WJH$PыT$L$tjL$+9p}'XP|$ t$pSL$5XXt PD$-tQf|$u@|$t3$_^][3茎 ÍImnnnn̸D$ jPL$ QD$D$ 1 tPjjjT$jRD$t P$hFhFh6ڋhFˋhF輋hF譋hF螋h|F菋hhF耋h\FqhPFbh@FSh0FDh`6/P <$}hFhhE hX6P܅(}hEhhE超 hE过t)P蝅,}hEhhEw hE耇hE<t 0 h86QP6h0647P 8̋D$T$ +hhEjj=hhEjj螇hhEjj 苇 =j贉hstcVhhEj ԃ t8xFt8u V讃 @VQF讃R3^j4hhEjj ކhhEjjdž̸ 薊S\$Wu_3[ Vt$0tJD$ t,L$ QP蔂|PR膂t$ Ul$(G=H?%x$x3        =wWtE=t.=t=uw m ] M ==t= u)  -GH@way$x3! t$, Mt 0L$0t5$*t$,EtD$0t9_u3L$$}uP薄 t >T$ ȁ=uuhGuV9_u1u+hFtL$$E]^_[ Áu$uhF謅t T$$E]^_[ ]^_3[ ÍIuuuv#vv6vvww,w3ww%wfwL$w4HT$t L$ ËT$ 3ËD$;t8V;up1H tpqHtp q A H @^̋D$Ul$EM M h Gu hGu  uM39   Ƀ ȉ  Ƀ ȉ@  Ƀဃ ȉ%  Ɂ ȉ%  Ɂ ȉ%  Ɂ ȉ39 ]   Ƀ ȉ   Ƀ ȉ=t=<t3 ȉø ȉSUl$(W339\$Vu$D$HXS3Ƀ;t@9tVj"khhEj Ye~tiVPd|4V'ejjh#hEh5hjd^[_átVPetjj^[3_Vdjjh+hEjAhhEh3hjfd[3_ø_̋D$t@3̋D$@4= =M=tylVøLV-=]$,Vø VøUøUøUøUø|Uø\UøDJޕPV   ǖKQ͖Ӗٖߖ !'-39?E!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!! !!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ̋D$@8-ttt4øVøVøVËD$@4= =)=t YøY-=$PYøYøYøYøYøYøYøYøYøYøYøxYøpYøhYø`YøXYøPYøHY=-=i$ @Yø8Yø0Yø(Yø YøYøYøYøYøXøXøXøXøXøXøXøXøXøXøXøXøXøX-tt XøXøxX=!- =$`pXøhXø`XøXXøPXøHXø@Xø8Xø0Xø(Xø XøXøXøXøXøWøWøWøWøWøW="-!=($WøWøWøWøWøWøWøWøWøWøxWøpWøhWø`WøXWøPWøHWø@Wø8Wø0Wø(Wø WøWøWøWøWøVøVøVøVøVøV="t=@tVøVøVÍIKQW]ciou{E;  IX^ "(.4:@FLRmsy;   ƞ̞Ҟ؞ޞ &,2;   I!ǟ͟ӟٟߟ msy;   ̋D$uYÃYt4̋D$uZÃYtY̋D$%s$<|ZøxZøtZøpZølZøhZødZø`Zø\ZøXZøTZøPZøLZøHZøDZø@Zø+]C^YW|$ uh-h\jChjM3_Vt$ ƘV'u h2h\jAhjM^3_S[^_̸UV3Wt$RPPu!hCh\jhjBM_^YËD$PjjlWM,hIh\jhj MW OD$ _^YËD$SUl$u HpPlQRjW RuHjWX Ru h^h\S3VUVD$L ][WND$ _^YhYh\j|hjcL][WbND$ _^Y̋L$D$ VQT$RD$D$jP9Ruhrh\j hjL3^ËL$ WVQV L _^SUl$ Vt$VK؃u$hh\h hjK^]3[SVK~}*hh\hhjgKSK^]3[ÍvW|4tPPSIQK8uHQ+Qu*D$RPOuQ,KfKSKTv Dtt PJ|$hh\jGjPJ>_u^E][Vt$ uhh\jChjJ3^S\$ ðSצu hh\jAhjHJ[3^W^Pu!hh\jhjJ_[3^VKVjW"P WJ_[^̸vQV3Wt$WOP/Mu!h0h\jhjI_^YËD$PjjlWJ,h6h\jhjkIWlKD$ _^YËD$S\$UujW kOuPKpSlQRjWhHOu hKh\U3VSaVD$K ][WJD$ _^YhFh\j|hjH][WJD$ _^Y̋L$ D$VQT$RjD$N uh_h\j hjuH3^ËD$WVPV K _^W|$ uhmh\jChj/H3_Vt$ ưV臤u hrh\jAhjG^3_S[^_̸vOV3Wt$WMP/Ku!hh\jhjG_^YËD$PjjlWH,hh\jhjkGWlID$ _^YËD$S\$UuKpSlQRjW EMuHjWh *Mu hh\U3VSVD$G ][WHD$ _^Yhh\j|hjF][WHD$ _^Y̋L$D$ VQT$RD$D$jPLuhh\j hjpF3^ËL$ WVQ VyF _^W|$ ujIh\jChj"F3_Vt$ ƘVzujNh\jAhjE^3_ËWP ^_̸fMV3Wt$GKPIuj_h\jhjE_^YËD$PjjlWF)jeh\jhjaEWbGD$ _^YËD$SUl$ujW mK!uvXHpPlQRjWJu*jzh\ShjD][WFD$ _^YVUVD$D][WFD$ _^Yjth\j|hjD][WFD$ _^Y̋D$ VPL$QjD uhh\j hjMD3^ËT$WVRVJD _^Vt$ uhh\jChjC3^S\$ ØSWu hh\jAhjC[3^WIu!hh\jhjC_[3^VEVjWIWC_[^̸JV3Wt$HPFu!hh\jhj"C_^YËD$PjjlWC,hh\jhjBWDD$ _^YËD$SUl$ujW H!uVXHpPlQRjWHu h h\S3VU[VD$#E ][WpDD$ _^Yhh\j|hjCB][WBDD$ _^Y̋L$ D$VQT$RjD$WV Dth8P@džFpNlPQjS Dt+WjjVngtCVpFlRPjSCuDȁ u%lu>|$W6>|$3t W#>_^S @][Y̸E3ĉ$|$U3V$D$l$0l$ l$8l$(l$4l$l$@l$uT$D$lT$D$|$lT$D$9t$T$D$D$|$$F$FDV$Fh$VH$F$Vl$$V$$$$$;t2P$$pR$$$YB;t2P$$R$$$B;t2P$$hR$$$A;t3xd$@u+ǿ$DŽ$$O;t$$ $$;~-P$$xR$$$CA;t'x@u+lj$,DŽ$0$4;t'x@u+lj$<DŽ$@$D;t'x@u+lj$LDŽ$P$TD$LUP@L$dUQ@T$|UR|@$UPl@$UQ\@(9nv$URD@9t!$UP/@jPjD$L@9t!$UQ@jPjD$j PjD$8>9t!$,UR>jPjD$P>9t!$<UP>jPjD$4>9t!$LUQx>j PjD$@d>jWjU> |$T$jjWL$jQD$$$>T$$RD$dP'>L$,QT$|R>D$4P$Q>T$D$\L$D;9PL$hL$$QT$$RD$$PL$TQ4؃yD$L;D$l !uT$\+T$DD$dLL$T$RD$HPV. u D$lp !u7D$\+D$DL$DD$dPQD$ v4uD$L?D$l4 T$dL$DD$\+‰D$\|$$|$,;9PD$$PL$lL$$QT$$RD$TP4؃yD$L;D$l !uL$\+L$DT$dDD$L$QT$HRD$P3 u D$l !u7D$\+D$DL$DD$dPQD$ 3uD$L?D$lN T$d+T$DT$\9|$,tCD$$ ~ D$L& EhD$$L$,PQUlR4D$8P,|$,|$$}hD$\|$4;L$D9PL$hL$$QT$$RD$$PL$TQ2؃yD$L;D$l!uT$\+T$DD$dLL$T$RD$HPL$Q2 u D$l\!u7D$\+D$DT$DD$dPRD$ b2uD$L?D$l D$d+D$DD$\9|$%D$`L$H|$$|$,;9PT$$RD$$L$lPL$$QT$TRJ+؃yD$L;D$lu!uD$\+D$DL$dTT$D$PL$HQT$R+ u D$lu!u7D$\+D$DD$dPD$D$HP*uD$L?D$luL$d+L$DD$,L$\;t(T$$RP*D$4P2$ |$,|$$L$DQQ*u D$l&D$xT$DD$t;t(_^][`D$LL$lT$LQh\Rjgj #$L$x+QP)tD$tt9(t U_^]3[`SVt$W|$h,_W)u4W=u4I=u4;=u4-=u4=u$_=_t4Ph_Wd) lu.ȁu %Ph^Rh^ @Ph^W) h^W)39^Dv"DHPh^W( C;^Drh^W(39^hv"LlQh^W( C;^hrhx^W(39^v"TRh^W[( cC;^rhd^WE(GFuh4HW((*)3ۅv#DPh^W' C;^rhP^W'u4HPhL^W' h0^W'u4HPhL^W' h^Wo'qu4HPhL^WC' KtPh]W"' *t7h]W ' jQRW&t]D$PjjjjVD$,D$,uQh]W& PJQRh]W|&tPh|]W[& ~gtPh`]W>& ~Jh\]W2&~8h@]W &~&P%PQh4]W%_^3[_^[V$P"ujah<_jhj3^ËD$WPjjjVyL$ QVV _^%P%%P%%P%%P%%P%%P% P%t%P%c%P%R%P|%A%Pq%0%Pf%%P[%%PP%$PE%$P:%@P$h`6hh5$h`6hh5$s P$hX6hh5$h_hhx_q$!Pl$ Pa$@q!PS$`!PH$m!P=$hl_hh\_#$hl_hhT_$hl_hhL_# !P#4辷 ̸djlh_j>3Ƀ ;ujoh_jAjvj 3ËT$HHH HHB J JVt$u3^W~ t Pi~t#~ t?t WfF Fv _t V^̸#3S\$D$D$;u[Ul$Vu W>jUD$,PSW.CSWEn$d Fv"^ 9F vFWF CD$~PNN;FWFCT$_^U][j UT$_^U][j UT$_^U][j U_D$ T$ ^U][j U_D$ T$ ^U][j UqD$T$_^U][ÍI>PPP≠&"3S\$D$D$;u[Ul$Vu W>jUD$,PSWBSWl$Fv"^ 9F vFWF KBD$~PNN;FWFBT$_^U][j UAT$_^U][j U%T$_^U][j U _D$ T$ ^U][j UD$T$_^U][ÍImD$SUVW|$o uu mt_^]3[ÍH~t$$V9eFN ;HuVl ;Hu VxlV^$tT$ D$L$RPQW _^][Ëv gT$ D$L$RPQV_^][_^3][Ã|$Vtfl_^][k_^][ËD$<]}jE_^E][ËD$=]_^E][Ë]_^][ÅtWWD$ T$O WP}8t.G$t PVhmh_jw$j,V{_ _^][ËD$ _0^][Ë__^][ËT$W_^][ËL$ T$QRPFP_^][V;؃N PPj Q{_^][jW{T$(D$$L$ RVPQRQW_^][ËG$;F PPV 7G$hh_j,jP _^][;|$ gF9F t P$thh_jj,WN3_FF ^][jWVGiSV\ht;t$j WO$QW_^][j Wi_^][j WW_^][Ë\$ C 8t P_V*jK W JC HW C J H W C JHW C JHS 39_^][ËL$ T$QRPF P_^][VVL$$_^][ËT$ L$RV QPR؃_^][ÐQk9iR,H     ̋D$H L$Vt^L$@ D$#L$QPLU^̋T$Vp@u+PD$ RP ^Whdu_ËD$VPZuW^3_Ã|$Vtg4gVjjmW^_̋D$VhPL$hQt)t%v >t@ 8tRP7^3^̋D$t9t@$uËP D$ _SP؃u[VWhdtJD$PYuWuSl_^3[VfVjjmWSWqu S>3_^[WPu_ËD$VPNtVWuWt V3^_̡PuhPh`jVt$W3;u_3^ËtPxQ|RPQR{PoQcRW$hdlpx|t_dž^Vt$W3;u_3^ËPQRPQRPQsRg$_dž^SVt$ 3W;=;/dhlpx;tP;|;tPh;;tPG;;tP&;tt;tP ;tW;tP;t:;tP;t;t!P;uhhHj1t;P;hhHjDh9j P QRPQRPQR$_^3[Ë_^[̋D$3;u3Édhlpx|tǀ̸4V3ĉD$0Vt$0$+[}" Yvu9 ,:HXjĚΚ֙™vlbXNKOW00pB>>":POpOOPB:: ?@?P??P> >0>0E5@?@?pB>>"5POpOOPB:: ?@?P??P> >0>00E5@?@?.\ssl\s2_srvr.cpB>>5:POpOOPB:: ?@?P??P> >0>0'0E5@?@?.\ssl\s2_clnt.cDES-CBC3-MD5DES-CBC-MD5IDEA-CBC-MD5EXP-RC2-CBC-MD5RC2-CBC-MD5EXP-RC4-MD5RC4-MD5SSLv2 part of OpenSSL 1.0.1c 10 May 2012A (A (A@!88.\ssl\s2_lib.cs->session->master_key_length >= 0 && s->session->master_key_length < (int)sizeof(s->session->master_key)error >= 0 && error <= (int)sizeof(buf)c->iv_len <= (int)sizeof(s->session->key_arg)s->s2->key_material_length <= sizeof s->s2->key_material.\ssl\s2_enc.c.\ssl\s2_pkt.cmac_size <= MAX_MAC_SIZEpp 0(0PpQ@5pp5 0(0PQ@5.\ssl\s3_srvr.cGOST signature length is %dpp5 0(0P@@5.\ssl\s3_clnt.cSRVRCLNTECDH-RSA-AES256-GCM-SHA384ECDH-RSA-AES128-GCM-SHA256ECDHE-RSA-AES256-GCM-SHA384ECDHE-RSA-AES128-GCM-SHA256ECDH-ECDSA-AES256-GCM-SHA384ECDH-ECDSA-AES128-GCM-SHA256ECDHE-ECDSA-AES256-GCM-SHA384ECDHE-ECDSA-AES128-GCM-SHA256ECDH-RSA-AES256-SHA384ECDH-RSA-AES128-SHA256ECDHE-RSA-AES256-SHA384ECDHE-RSA-AES128-SHA256ECDH-ECDSA-AES256-SHA384ECDH-ECDSA-AES128-SHA256ECDHE-ECDSA-AES256-SHA384ECDHE-ECDSA-AES128-SHA256SRP-DSS-AES-256-CBC-SHASRP-RSA-AES-256-CBC-SHASRP-AES-256-CBC-SHASRP-DSS-AES-128-CBC-SHASRP-RSA-AES-128-CBC-SHASRP-AES-128-CBC-SHASRP-DSS-3DES-EDE-CBC-SHASRP-RSA-3DES-EDE-CBC-SHASRP-3DES-EDE-CBC-SHAAECDH-AES256-SHAAECDH-AES128-SHAAECDH-DES-CBC3-SHAAECDH-RC4-SHAAECDH-NULL-SHAECDHE-RSA-AES256-SHAECDHE-RSA-AES128-SHAECDHE-RSA-DES-CBC3-SHAECDHE-RSA-RC4-SHAECDHE-RSA-NULL-SHAECDH-RSA-AES256-SHAECDH-RSA-AES128-SHAECDH-RSA-DES-CBC3-SHAECDH-RSA-RC4-SHAECDH-RSA-NULL-SHAECDHE-ECDSA-AES256-SHAECDHE-ECDSA-AES128-SHAECDHE-ECDSA-DES-CBC3-SHAECDHE-ECDSA-RC4-SHAECDHE-ECDSA-NULL-SHAECDH-ECDSA-AES256-SHAECDH-ECDSA-AES128-SHAECDH-ECDSA-DES-CBC3-SHAECDH-ECDSA-RC4-SHAECDH-ECDSA-NULL-SHAADH-AES256-GCM-SHA384ADH-AES128-GCM-SHA256DH-DSS-AES256-GCM-SHA384DH-DSS-AES128-GCM-SHA256DHE-DSS-AES256-GCM-SHA384DHE-DSS-AES128-GCM-SHA256DH-RSA-AES256-GCM-SHA384DH-RSA-AES128-GCM-SHA256DHE-RSA-AES256-GCM-SHA384DHE-RSA-AES128-GCM-SHA256AES256-GCM-SHA384AES128-GCM-SHA256ADH-SEED-SHADHE-RSA-SEED-SHADHE-DSS-SEED-SHADH-RSA-SEED-SHADH-DSS-SEED-SHASEED-SHAPSK-AES256-CBC-SHAPSK-AES128-CBC-SHAPSK-3DES-EDE-CBC-SHAPSK-RC4-SHAADH-CAMELLIA256-SHADHE-RSA-CAMELLIA256-SHADHE-DSS-CAMELLIA256-SHADH-RSA-CAMELLIA256-SHADH-DSS-CAMELLIA256-SHACAMELLIA256-SHAGOST2001-NULL-GOST94GOST94-NULL-GOST94GOST2001-GOST89-GOST89GOST94-GOST89-GOST89ADH-AES256-SHA256ADH-AES128-SHA256DHE-RSA-AES256-SHA256DHE-DSS-AES256-SHA256DH-RSA-AES256-SHA256DH-DSS-AES256-SHA256DHE-RSA-AES128-SHA256ADH-CAMELLIA128-SHADHE-RSA-CAMELLIA128-SHADHE-DSS-CAMELLIA128-SHADH-RSA-CAMELLIA128-SHADH-DSS-CAMELLIA128-SHACAMELLIA128-SHADHE-DSS-AES128-SHA256DH-RSA-AES128-SHA256DH-DSS-AES128-SHA256AES256-SHA256AES128-SHA256NULL-SHA256ADH-AES256-SHADHE-RSA-AES256-SHADHE-DSS-AES256-SHADH-RSA-AES256-SHADH-DSS-AES256-SHAAES256-SHAADH-AES128-SHADHE-RSA-AES128-SHADHE-DSS-AES128-SHADH-RSA-AES128-SHADH-DSS-AES128-SHAAES128-SHAADH-DES-CBC3-SHAADH-DES-CBC-SHAEXP-ADH-DES-CBC-SHAADH-RC4-MD5EXP-ADH-RC4-MD5EDH-RSA-DES-CBC3-SHAEDH-RSA-DES-CBC-SHAEXP-EDH-RSA-DES-CBC-SHAEDH-DSS-DES-CBC3-SHAEDH-DSS-DES-CBC-SHAEXP-EDH-DSS-DES-CBC-SHADH-RSA-DES-CBC3-SHADH-RSA-DES-CBC-SHAEXP-DH-RSA-DES-CBC-SHADH-DSS-DES-CBC3-SHADH-DSS-DES-CBC-SHAEXP-DH-DSS-DES-CBC-SHADES-CBC3-SHADES-CBC-SHAEXP-DES-CBC-SHAIDEA-CBC-SHARC4-SHANULL-SHANULL-MD5SSLv3 part of OpenSSL 1.0.1c 10 May 2012.\ssl\s3_lib.cCCCBBA.\ssl\s3_enc.cm.\ssl\s3_pkt.cmac_size >= 0SSL alert number %d.\ssl\s3_both.ci <= EVP_MAX_MD_SIZEIJIP7BE`FF55:(0EE5@E`E/0E5IJIP75E`FF55:(0EE5@E`E/0E5.\ssl\s23_srvr.cCONNECTPUT HEAD POST GET IJI5BE`FF55:(0EE5@E`E90E5.\ssl\s23_clnt.c.\ssl\s23_lib.cIJI 0(0PpH5IJI 0(0PpH5IJI 0(0PpH5IJI5 0(0PH5IJI5 0(0PH5IJI5 0(0PH5IJI5 0(0PPI5IJI5 0(0PPI5IJI5 0(0PPI5server finishedclient finishedTLSv1 part of OpenSSL 1.0.1c 10 May 2012.\ssl\t1_lib.c.\ssl\t1_enc.cchunk >= 0key expansionIV blockclient write keyserver write key%s:%d: rec->data != rec->input n >= 0t > 0t >= 0master secret `  @ P`АT5 `5  @ P`T5.\ssl\d1_srvr.c `5  @ P`T5.\ssl\d1_clnt.cDTLSv1 part of OpenSSL 1.0.1c 10 May 2012.\ssl\d1_lib.c.\ssl\d1_pkt.c0len <= SSL3_RT_MAX_PLAIN_LENGTH.\ssl\d1_both.c((long)msg_hdr->msg_len) > 0invalid state reached %s:%ds->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_nums->d1->w_msg_hdr.msg_len + ((s->version==DTLS1_VERSION)?DTLS1_CCS_HEADER_LENGTH:3) == (unsigned int)s->init_nums->init_off == 0len == (unsigned int)retlen >= DTLS1_HM_HEADER_LENGTHs->init_off > DTLS1_HM_HEADER_LENGTHs->init_num == (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTHs->d1->mtu >= dtls1_min_mtu()retransmit: message %d non-existant dtls1_retransmit_message() failed .\ssl\d1_enc.cSRTP_AES128_CM_SHA1_32SRTP_AES128_CM_SHA1_80.\ssl\d1_srtp.cOpenSSL 1.0.1c 10 May 2012.\ssl\ssl_lib.cALL:!aNULL:!eNULL:!SSLv2SSLv2unknownSSLv3TLSv1TLSv1.1TLSv1.2s->sid_ctx_length <= sizeof s->sid_ctxssl3-sha1ssl3-md5ssl2-md5SSL for verify callback.\ssl\ssl_cert.cssl_serverssl_clientOPENSSL_DIR_read(&ctx, '')%s/%s.\ssl\ssl_sess.cSSL SESSION PARAMETERS%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s%s FIPSHIGHMEDIUMLOWEXPORT56EXPORT40EXPORTEXPSHA384SHA256GOST89MACGOST94SHASHA1MD5CAMELLIACAMELLIA256CAMELLIA128AESGCMAESAES256AES128eNULLSEEDIDEARC2RC43DESDESSRPPSKAECDHADHRSAKRB5NULLEECDHEDHaGOSTaGOST01aGOST94aPSKECDSAaECDSAaECDHaDHaNULLaKRB5DSSaDSSaRSAkGOSTkSRPkPSKECDHkEECDHkECDHkECDHekECDHrkKRB5DHkEDHkDHkDHdkDHrkRSACOMPLEMENTOFDEFAULTCOMPLEMENTOFALLALL77 777777777 7@7`7|7t7l7d7\7T7P7H7 @7<747,7@$7@77 77766 6 666666666666 6@6 6060|6p6d6`6X6T6L6@68606 444,6$66 66 6@55gost-macssl_mac_secret_size[SSL_MD_GOST94_IDX] >= 0md_gost94ssl_mac_secret_size[SSL_MD_SHA1_IDX] >= 0.\ssl\ssl_ciph.cssl_mac_secret_size[SSL_MD_MD5_IDX] >= 0id-aes256-GCMid-aes128-GCMSEED-CBCgost89-cntCAMELLIA-256-CBCCAMELLIA-128-CBCAES-256-CBCAES-128-CBCIDEA-CBCRC2-CBCDES-EDE3-CBCDES-CBCAES-256-CBC-HMAC-SHA1AES-128-CBC-HMAC-SHA1RC4-HMAC-MD5gost2001gost94STRENGTHDEFAULTBuffer too smallOPENSSL_malloc ErrorAEADAESGCM(128)AESGCM(256)SEED(128)AES(256)Camellia(128)Camellia(256)AES(128)IDEA(128)RC2(128)RC2(56)RC2(40)RC4(128)RC4(64)RC4(56)RC4(40)3DES(168)DES(56)DES(40)NoneECDH/ECDSAECDH/RSADH(1024)DH(512)DH/DSSDH/RSARSA(1024)RSA(512) exportTLSv1/SSLv3(NONE)before/connect initializationbefore/accept initializationunknown statebefore SSL initializationSSLv2/v3 read client hello BSSL renegotiate ciphersSSLv2/v3 read client hello ADTLS1 write hello verify request BDTLS1 write hello verify request ASSLv3 read certificate verify BSSLv3 read certificate verify ASSLv3 read client key exchange BSSLv3 read client key exchange ASSLv3 read client certificate BSSLv3 read client certificate ASSLv3 write server done BSSLv3 write server done ASSLv3 write session ticket BSSLv3 write session ticket ASSLv3 write certificate request BSSLv3 write certificate request ASSLv3 write key exchange BSSLv3 write key exchange ASSLv3 write certificate BSSLv3 write certificate ASSLv3 write server hello BSSLv3 write server hello ASSLv3 write hello request CSSLv3 write hello request BSSLv3 write hello request ASSLv3 read client hello CSSLv3 read client hello BSSLv3 read finished BSSLv3 read finished ASSLv3 read change cipher spec BSSLv3 read change cipher spec ASSLv3 write finished BSSLv3 write finished ASSLv3 write change cipher spec BSSLv3 write change cipher spec ASSLv3 read client hello ASSLv3 flush dataSSLv2 X509 read server certificateSSLv2 write request certificate DSSLv2 write request certificate CSSLv2 write request certificate BSSLv2 write request certificate ASSLv2 write server finished BSSLv2 write server finished ASSLv2 read client finished BSSLv2 read client finished ASSLv2 write server verify CSSLv2 write server verify BSSLv2 write server verify ASSLv2 read client master key BSSLv2 read client master key ASSLv2 write server hello BSSLv2 write server hello ASSLv2 read client hello CSSLv2 read client hello BSSLv2 read client hello ASSLv2 server start encryptionok/accept SSL initializationbefore accept initializationSSLv2/v3 write client hello BSSLv2/v3 read server hello ASSLv2/v3 read server hello BSSLv2/v3 write client hello ADTLS1 read hello verify request BDTLS1 read hello verify request ASSLv3 write certificate verify BSSLv3 write certificate verify ASSLv3 write client key exchange BSSLv3 write client key exchange ASSLv3 write client certificate DSSLv3 write client certificate CSSLv3 write client certificate BSSLv3 write client certificate ASSLv3 read server done BSSLv3 read server done ASSLv3 read server session ticket BSSLv3 read server session ticket ASSLv3 read server certificate request BSSLv3 read server certificate request ASSLv3 read server key exchange BSSLv3 read server key exchange ASSLv3 read server certificate BSSLv3 read server certificate ASSLv3 read server hello BSSLv3 read server hello ASSLv3 write client hello BSSLv3 write client hello ASSLv2 X509 read client certificateSSLv2 read server finished BSSLv2 read server finished ASSLv2 read server verify BSSLv2 read server verify ASSLv2 write client certificate DSSLv2 write client certificate CSSLv2 write client certificate BSSLv2 write client certificate ASSLv2 write client finished BSSLv2 write client finished ASSLv2 write client master key BSSLv2 write client master key ASSLv2 read server hello BSSLv2 read server hello ASSLv2 write client hello BSSLv2 write client hello ASSLv2 client start encryptionok/connect SSL initializationbefore connect initializationSSL negotiation finished successfullyread headerread bodyread done23RCHBPINIT UNKWN 23RCHADWCHVBDWCHVA3RCV_B3RCV_A3RCKEB3RCKEA3RCC_B3RCC_A3WSD_B3WSD_A3WCR_B3WCR_A3WSKEB3WSKEA3WSC_B3WSC_A3WSH_B3WSH_A3RCH_C3RCH_B3WHR_C3WHR_B3WHR_A3RFINB3RFINA3RCCSB3RCCSA3WFINB3WFINA3WCCSB3WCCSA3RCH_A3FLUSH2X9GSC2SRC_D2SRC_C2SRC_B2SRC_A2SSF_B2SSF_A2GCF_B2GCF_A2SSV_C2SSV_B2SSV_A2GCMKA2SSH_B2SSH_A2GCH_C2GCH_B2GCH_A2SSENCAINIT 23WCHB23RSHA23WCHADRCHVBDRCHVA3WCV_B3WCV_A3WCKEB3WCKEA3WCC_D3WCC_C3WCC_B3WCC_A3RSD_B3RSD_A3RCR_B3RCR_A3RSKEB3RSKEA3RSC_B3RSC_A3RSH_B3RSH_A3WCH_B3WCH_A2X9GCC2GSF_B2GSF_A2GSV_B2GSV_A2SCC_D2SCC_C2SCC_B2SCC_A2SCF_B2SCF_A2SCMKB2SCMKA2GSH_B2GSH_A2SCH_B2SCH_A2CSENCCINIT SSLOK fatalwarningUFWUKUPBHBRUNCOUENRUSIEISPVERCYDEADCARODCIPCUCECRUCBCNCHFDFBMUMCNunknown PSK identitybad certificate hash valuebad certificate status responseunrecognized namecertificate unobtainableunsupported extensionno renegotiationuser canceledinternal errorinsufficient securityprotocol versionexport restrictiondecrypt errordecode erroraccess deniedunknown CArecord overflowdecryption failedillegal parametercertificate unknowncertificate expiredcertificate revokedunsupported certificatebad certificateno certificatehandshake failuredecompression failurebad record macunexpected_messageclose notifyRHRBRD.\ssl\ssl_rsa.c.\ssl\ssl_asn1.cos.length <= (int)sizeof(ret->session_id)%ld (%s) Verify return code: Timeout : %ld (sec) Start Time: %ld Compression: %d (%s) Compression: %d TLS session ticket: TLS session ticket lifetime hint: %ld (seconds) SRP username: PSK identity hint: %s PSK identity: Key-Arg : Master-Key: Session-ID-ctx: %02X Session-ID: Cipher : %s Cipher : %04lX Cipher : %06lX Protocol : %s DTLSv1-badDTLSv1SSL-Session: .\ssl\ssl_txt.cdss1DSS1DSA-SHA1-oldDSA-SHA1RSA-SHA1-2RSA-SHA1ssl.\ssl\bio_ssl.cx509 verification setup problemsx509 libwrong version numberwrong ssl versionwrong signature typewrong signature sizewrong signature lengthwrong number of key bitswrong message typewrong cipher returnedwrite bio not setuse srtp not negotiatedunsupported status typeunsupported ssl versionunsupported protocolunsupported elliptic curveunsupported digest typeunsupported compression algorithmunsupported cipherunsafe legacy renegotiation disabledunknown ssl versionunknown remote error typeunknown protocolunknown pkey typeunknown key exchange typeunknown digestunknown cipher typeunknown cipher returnedunknown certificate typeunknown alert typeuninitializedunexpected recordunexpected messageunable to load ssl3 sha1 routinesunable to load ssl3 md5 routinesunable to load ssl2 md5 routinesunable to find ssl methodunable to find public key parametersunable to find ecdh parametersunable to find dh parametersunable to extract public keyunable to decode ecdh certsunable to decode dh certstried to use unsupported ciphertls rsa encrypted value length is wrongtls peer did not respond with certificate listtls invalid ecpointformat listtls illegal exporter labelheartbeat request already pendingpeer does not accept heartbeartstls client cert req with anon ciphertlsv1 unsupported extensiontlsv1 unrecognized nametlsv1 certificate unobtainabletlsv1 bad certificate status responsetlsv1 bad certificate hash valuetlsv1 alert user cancelledtlsv1 alert unknown catlsv1 alert record overflowtlsv1 alert protocol versiontlsv1 alert no renegotiationtlsv1 alert internal errortlsv1 alert insufficient securitytlsv1 alert export restrictiontlsv1 alert decrypt errortlsv1 alert decryption failedtlsv1 alert decode errortlsv1 alert access deniedssl session id is differentssl session id has bad lengthssl session id context too longssl session id conflictssl session id callback failedssl library has no ciphersssl handshake failuressl ctx has no default ssl versionsslv3 alert unsupported certificatesslv3 alert unexpected messagesslv3 alert no certificatesslv3 alert illegal parametersslv3 alert handshake failuresslv3 alert decompression failuresslv3 alert certificate unknownsslv3 alert certificate revokedsslv3 alert certificate expiredsslv3 alert bad record macsslv3 alert bad certificatessl3 session id too shortssl3 session id too longssl3 ext invalid servername typessl3 ext invalid servernamessl3 ext invalid ecpointformatssl2 connection id too longssl23 doing session id reusesrtp unknown protection profilesrtp protection profile list too longsrtp could not allocate profileserror with the srp paramssignature for non signing certificatesignature algorithms errorshort readsession id context uninitializedserverhello tlsextscsv received when renegotiatingreuse cipher list not zeroreuse cert type not zeroreuse cert length not zerorequired compresssion algorithm missingrequired cipher missingrenegotiation mismatchrenegotiation encoding errrenegotiate ext too longrecord too smallrecord too largerecord length mismatchread wrong packet typeread timeout expiredread bio not setpublic key not rsapublic key is not rsapublic key encrypt errorpsk no server cbpsk no client cbpsk identity not foundprotocol is shutdownproblems mapping cipher functionspre mac length too longpeer error unsupported certificate typepeer error no cipherpeer error no certificatepeer error certificatepeer errorpeer did not return a certificatepath too longparse tlsextpacket length too longopaque PRF input too longonly tls allowed in fips modeold session compression algorithm not returnedold session cipher not returnednull ssl method passednull ssl ctxno verify callbackno srtp profilesno shared cipherdigest requred for handshake isn't computedno publickeyno protocols availableno private key assignedno privatekeyno method specifiedPeer haven't sent GOST certificate, required for selected ciphersuiteno compression specifiedno client cert receivedno client cert methodno cipher matchno cipher listno ciphers specifiedno ciphers passedno ciphers availableno certificate specifiedno certificate setno certificate returnedno certificate assignedno certificates returnednon sslv2 initial packetmultiple sgc restartsmissing verify messagemissing tmp rsa pkeymissing tmp rsa keymissing tmp ecdh keymissing tmp dh keycan't find SRP server parammissing rsa signing certmissing rsa encrypting certmissing rsa certificatemissing export tmp rsa keymissing export tmp dh keymissing dsa signing certmissing dh rsa certmissing dh keymissing dh dsa certmessage too longlibrary has no cipherslibrary buglength too shortlength mismatchkrb5 server tkt skewkrb5 server tkt not yet validkrb5 server tkt expiredkrb5 server rd_req (keytab perms?)krb5 server initkrb5 server bad ticketkrb5 client mk_req (expired tkt?)krb5 client initkrb5 client get credkrb5 client cc principal (no tkt?)krb5key arg too longinvalid trustinvalid ticket keys lengthinvalid status responseinvalid srp usernameinvalid purposeinvalid compression algorithminvalid commandinvalid challenge lengthinconsistent compressionillegal paddinghttp requesthttps proxy requestgot next proto without seeing extensiongot next proto before a ccsgot a fin before a ccsextra data in messageexcessive message sizeerror in received cipher listerror generating tmp rsa keyencrypted length too longempty srtp protection profile listecgroup too large for cipherecc cert should have sha1 signatureecc cert should have rsa signatureecc cert not for signingecc cert not for key agreementduplicate compression iddtls message too bigdigest check faileddh public value length is wrongdecryption failed or bad record macdata length too longdata between ccs and finishedcookie mismatchconnection type not setconnection id is differentcompression library errorcompression id not within private rangecompression failurecompression disabledcompressed length too longclienthello tlsextcipher table src errorcipher or hash unavailablecipher code wrong lengthchallenge is differentcert length mismatchcertificate verify failedccs received earlyca dn too longca dn length mismatchbn libblock cipher pad is wrongbio not setbad write retrybad statebad ssl session id lengthbad ssl filetypebad srtp protection profile listbad srtp mki valuebad srp s lengthbad srp n lengthbad srp g lengthbad srp b lengthbad srp a lengthbad signaturebad rsa signaturebad rsa modulus lengthbad rsa e lengthbad rsa encryptbad rsa decryptbad response argumentbad psk identity hint lengthbad protocol version numberbad packet lengthbad message typebad mac lengthbad mac decodebad lengthbad hello requestbad handshake lengthbad ecpointbad ecdsa signaturebad ecc certbad dsa signaturebad digest lengthbad dh p lengthbad dh pub key lengthbad dh g lengthbad decompressionbad data returned by callbackbad checksumbad change cipher specbad authentication typebad alert recordattempt to reuse session in different contextapp data in handshakeWRITE_PENDINGTLS1_SETUP_KEY_BLOCKtls1_prfTLS1_PREPARE_SERVERHELLO_TLSEXTTLS1_PREPARE_CLIENTHELLO_TLSEXTSSL_F_TLS1_HEARTBEATTLS1_EXPORT_KEYING_MATERIALTLS1_ENCTLS1_CHECK_SERVERHELLO_TLSEXTTLS1_CHANGE_CIPHER_STATEtls1_cert_verify_macSSL_writeSSL_VERIFY_CERT_CHAINSSL_use_RSAPrivateKey_fileSSL_use_RSAPrivateKey_ASN1SSL_use_RSAPrivateKeySSL_use_psk_identity_hintSSL_use_PrivateKey_fileSSL_use_PrivateKey_ASN1SSL_use_PrivateKeySSL_use_certificate_fileSSL_use_certificate_ASN1SSL_use_certificateSSL_UNDEFINED_VOID_FUNCTIONSSL_UNDEFINED_FUNCTIONSSL_UNDEFINED_CONST_FUNCTIONSSL_SRP_CTX_initSSL_shutdownSSL_set_wfdSSL_set_trustSSL_set_session_ticket_extSSL_set_session_id_contextSSL_set_sessionSSL_set_rfdSSL_set_purposeSSL_SET_PKEYSSL_set_fdSSL_set_cipher_listSSL_SET_CERTSSL_SESS_CERT_NEWSSL_SESSION_set1_id_contextSSL_SESSION_print_fpSSL_SESSION_newSSL_RSA_PUBLIC_ENCRYPTSSL_RSA_PRIVATE_DECRYPTSSL_readSSL_PREPARE_SERVERHELLO_TLSEXTSSL_PREPARE_CLIENTHELLO_TLSEXTSSL_peekSSL_PARSE_SERVERHELLO_USE_SRTP_EXTSSL_PARSE_SERVERHELLO_TLSEXTSSL_PARSE_SERVERHELLO_RENEGOTIATE_EXTSSL_PARSE_CLIENTHELLO_USE_SRTP_EXTSSL_PARSE_CLIENTHELLO_TLSEXTSSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXTSSL_newSSL_load_client_CA_fileSSL_INIT_WBIO_BUFFERSSL_GET_SIGN_PKEYSSL_GET_SERVER_SEND_CERTSSL_GET_PREV_SESSIONSSL_GET_NEW_SESSIONSSL_do_handshakeSSL_CTX_use_RSAPrivateKey_fileSSL_CTX_use_RSAPrivateKey_ASN1SSL_CTX_use_RSAPrivateKeySSL_CTX_use_psk_identity_hintSSL_CTX_use_PrivateKey_fileSSL_CTX_use_PrivateKey_ASN1SSL_CTX_use_PrivateKeySSL_CTX_use_certificate_fileSSL_CTX_use_certificate_chain_fileSSL_CTX_use_certificate_ASN1SSL_CTX_use_certificateSSL_CTX_set_trustSSL_CTX_set_ssl_versionSSL_CTX_set_session_id_contextSSL_CTX_set_purposeSSL_CTX_set_client_cert_engineSSL_CTX_set_cipher_listSSL_CTX_newSSL_CTX_MAKE_PROFILESSSL_CTX_check_private_keySSL_ctrlSSL_CREATE_CIPHER_LISTSSL_COMP_add_compression_methodSSL_clearSSL_CIPHER_STRENGTH_SORTSSL_CIPHER_PROCESS_RULESTRSSL_CHECK_SRVR_ECC_CERT_AND_ALGSSL_CHECK_SERVERHELLO_TLSEXTSSL_check_private_keySSL_CERT_NEWSSL_CERT_INSTANTIATESSL_CERT_INSTSSL_CERT_DUPSSL_BYTES_TO_CIPHER_LISTSSL_BAD_METHODSSL_ADD_SERVERHELLO_USE_SRTP_EXTSSL_ADD_SERVERHELLO_TLSEXTSSL_ADD_SERVERHELLO_RENEGOTIATE_EXTSSL_add_file_cert_subjects_to_stackSSL_add_dir_cert_subjects_to_stackSSL_ADD_CLIENTHELLO_USE_SRTP_EXTSSL_ADD_CLIENTHELLO_TLSEXTSSL_ADD_CLIENTHELLO_RENEGOTIATE_EXTSSL3_WRITE_PENDINGSSL3_WRITE_BYTESSSL3_SETUP_WRITE_BUFFERSSL3_SETUP_READ_BUFFERSSL3_SETUP_KEY_BLOCKSSL3_SEND_SERVER_KEY_EXCHANGESSL3_SEND_SERVER_HELLOSSL3_SEND_SERVER_CERTIFICATESSL3_SEND_CLIENT_VERIFYSSL3_SEND_CLIENT_KEY_EXCHANGESSL3_SEND_CLIENT_CERTIFICATESSL3_SEND_CERTIFICATE_REQUESTSSL3_READ_NSSL3_READ_BYTESSSL3_PEEKSSL3_OUTPUT_CERT_CHAINSSL3_NEW_SESSION_TICKETssl3_handshake_macSSL3_GET_SERVER_HELLOSSL3_GET_SERVER_DONESSL3_GET_SERVER_CERTIFICATESSL3_GET_RECORDSSL3_GET_NEXT_PROTOSSL3_GET_NEW_SESSION_TICKETSSL3_GET_MESSAGESSL3_GET_KEY_EXCHANGESSL3_GET_FINISHEDSSL3_GET_CLIENT_KEY_EXCHANGESSL3_GET_CLIENT_HELLOSSL3_GET_CLIENT_CERTIFICATESSL3_GET_CERT_VERIFYSSL3_GET_CERT_STATUSSSL3_GET_CERTIFICATE_REQUESTSSL3_GENERATE_KEY_BLOCKSSL3_ENCSSL3_DO_CHANGE_CIPHER_SPECSSL3_DIGEST_CACHED_RECORDSSSL3_CTX_CTRLSSL3_CTRLSSL3_CONNECTSSL3_CLIENT_HELLOSSL3_CHECK_CLIENT_HELLOSSL3_CHECK_CERT_AND_ALGORITHMSSL3_CHANGE_CIPHER_STATESSL3_CALLBACK_CTRLSSL3_ADD_CERT_TO_BUFSSL3_ACCEPTSSL2_WRITESSL2_SET_CERTIFICATESSL2_READ_INTERNALSSL2_READSSL2_PEEKSSL2_GENERATE_KEY_MATERIALSSL2_ENC_INITSSL2_CONNECTSSL2_ACCEPTSSL23_WRITESSL23_READSSL23_PEEKSSL23_GET_SERVER_HELLOSSL23_GET_CLIENT_HELLOSSL23_CONNECTSSL23_CLIENT_HELLOSSL23_ACCEPTSERVER_VERIFYSERVER_HELLOSERVER_FINISHREQUEST_CERTIFICATEREAD_Ni2d_SSL_SESSIONGET_SERVER_VERIFYGET_SERVER_HELLOGET_SERVER_FINISHEDGET_CLIENT_MASTER_KEYGET_CLIENT_HELLOGET_CLIENT_FINISHEDDTLS1_WRITE_APP_DATA_BYTESDTLS1_SEND_SERVER_KEY_EXCHANGEDTLS1_SEND_SERVER_HELLODTLS1_SEND_SERVER_CERTIFICATEDTLS1_SEND_HELLO_VERIFY_REQUESTDTLS1_SEND_CLIENT_VERIFYDTLS1_SEND_CLIENT_KEY_EXCHANGEDTLS1_SEND_CLIENT_CERTIFICATEDTLS1_SEND_CERTIFICATE_REQUESTDTLS1_READ_FAILEDDTLS1_READ_BYTESDTLS1_PROCESS_RECORDDTLS1_PROCESS_OUT_OF_SEQ_MESSAGEDTLS1_PREPROCESS_FRAGMENTDTLS1_OUTPUT_CERT_CHAINDTLS1_HEARTBEATDTLS1_HANDLE_TIMEOUTDTLS1_GET_RECORDDTLS1_GET_MESSAGE_FRAGMENTDTLS1_GET_MESSAGEDTLS1_GET_HELLO_VERIFYDTLS1_ENCDTLS1_CONNECTDTLS1_CLIENT_HELLODTLS1_CHECK_TIMEOUT_NUMDTLS1_BUFFER_RECORDDTLS1_ADD_CERT_TO_BUFDTLS1_ACCEPTDO_SSL3_WRITEDO_DTLS1_WRITEd2i_SSL_SESSIONCLIENT_MASTER_KEYCLIENT_HELLOCLIENT_FINISHEDCLIENT_CERTIFICATE.\ssl\tls_srp.c.\ssl\t1_reneg.c!expected_len || s->s3->previous_server_finished_len!expected_len || s->s3->previous_client_finished_len@HRSDSk|RB0ͱrD:\CFILES\Projects\WinSSL\openssl-1.0.1c\out32dll\ssleay32.pdbauq@DȘʙl\F&DXl֛, % F k !U4! x C N "Ym'8^ +x noj o   bN.q < l O{vBzR{ ; o Mb= <] /m <k DAWZ  c HI0 N_yx39noRR   4 U 0N` x?%  ~ B V CA5b G | rz l:vt2 m u|Jw?L ]D I porqwy{;{: %#86Ct ' z VXM%J0 S EI>0$+[}" Yvu9 ,:HXjĚΚ֙™vlbXNLIBEAY32.dll_time32&memcpy*memset(memmove[strncpyfprintf__iob_funcZstrncmp_ftime32Nstrchrp_errnoabortMSVCR90.dllj_encode_pointer_malloc_crtfreek_encoded_null`_decode_pointer_initterm_initterm_e_amsg_exit _adjust_fdivj__CppXcptFilterK_crt_debugger_hook__clean_type_info_names_internal_unlock__dllonexitv_lock_onexits_except_handler4_commonsSetLastErrorGetLastErrorInterlockedExchangeSleepInterlockedCompareExchangeTerminateProcessGetCurrentProcessUnhandledExceptionFilterSetUnhandledExceptionFilterIsDebuggerPresentDisableThreadLibraryCallsQueryPerformanceCounterGetTickCountGetCurrentThreadIdGetCurrentProcessIdyGetSystemTimeAsFileTimeKERNEL32.dllKOƨj0` Yk !0k`+PX@]Fm0$X,-Яp@p@` ж_`^OY`00>O DL`W0B6@$#`X@pJP%P5!@YPp?P` K$WPLa 5PD0P E/9>  'Q0p0pK670@0b@b bb:8p9`9:p8@^ ^80:8]89:9e89899P:]9H IIpP0;:bb::PZ;P;[@ -p ,, 0Pp]p# !` ==p;;Г07P70_d88e0ee@ee eePe88p((`e;P=`f=`=@<@=0ffp= =f@cbc` `H@IHP0p`0Pp`p`=0e0I`bH=9PPH0*0))(P*P_Өݨ0AVdyҩAXl~ɪ&<Pfȫ+E`t߬2Me}ӭ 'Ba7Qjѯ ?VzŰ %9Uqѱ9SrƲ$5Kgijܳ/G\tִ+A\j|ŵֵ޵ 1BRfzԶ$G\gxշ.;NZxʸ۸ !7Jbwʹ&.7CL\xϺ޺#:P^nyܻ2>Niͼ#;Smνڽ %;Nf~ʾ޾*6?I^lʿ׿&<Kauxy{ ,-0'KNL\MI  5$ hb&.G;CDH=Ee %Si !UQJ"#$%&'W()*+,|-.`/c0367~89:;<}/(>?d"#@A<>BgADEFGHIJKLMN7OPf4!QRSTURV +)WXY213?@Z[a ]^_O`abcdefghij*kmnopqrstu98:T]Vvw SSLEAY32.dllBIO_f_sslBIO_new_buffer_ssl_connectBIO_new_sslBIO_new_ssl_connectBIO_ssl_copy_session_idBIO_ssl_shutdownDTLSv1_client_methodDTLSv1_methodDTLSv1_server_methodERR_load_SSL_stringsPEM_read_SSL_SESSIONPEM_read_bio_SSL_SESSIONPEM_write_SSL_SESSIONPEM_write_bio_SSL_SESSIONSRP_Calc_A_paramSRP_generate_client_master_secretSRP_generate_server_master_secretSSL_CIPHER_descriptionSSL_CIPHER_get_bitsSSL_CIPHER_get_idSSL_CIPHER_get_nameSSL_CIPHER_get_versionSSL_COMP_add_compression_methodSSL_COMP_get_compression_methodsSSL_COMP_get_nameSSL_CTX_SRP_CTX_freeSSL_CTX_SRP_CTX_initSSL_CTX_add_client_CASSL_CTX_add_sessionSSL_CTX_callback_ctrlSSL_CTX_check_private_keySSL_CTX_ctrlSSL_CTX_flush_sessionsSSL_CTX_freeSSL_CTX_get_cert_storeSSL_CTX_get_client_CA_listSSL_CTX_get_client_cert_cbSSL_CTX_get_ex_dataSSL_CTX_get_ex_new_indexSSL_CTX_get_info_callbackSSL_CTX_get_quiet_shutdownSSL_CTX_get_timeoutSSL_CTX_get_verify_callbackSSL_CTX_get_verify_depthSSL_CTX_get_verify_modeSSL_CTX_load_verify_locationsSSL_CTX_newSSL_CTX_remove_sessionSSL_CTX_sess_get_get_cbSSL_CTX_sess_get_new_cbSSL_CTX_sess_get_remove_cbSSL_CTX_sess_set_get_cbSSL_CTX_sess_set_new_cbSSL_CTX_sess_set_remove_cbSSL_CTX_sessionsSSL_CTX_set1_paramSSL_CTX_set_cert_storeSSL_CTX_set_cert_verify_callbackSSL_CTX_set_cipher_listSSL_CTX_set_client_CA_listSSL_CTX_set_client_cert_cbSSL_CTX_set_client_cert_engineSSL_CTX_set_cookie_generate_cbSSL_CTX_set_cookie_verify_cbSSL_CTX_set_default_passwd_cbSSL_CTX_set_default_passwd_cb_userdataSSL_CTX_set_default_verify_pathsSSL_CTX_set_ex_dataSSL_CTX_set_generate_session_idSSL_CTX_set_info_callbackSSL_CTX_set_msg_callbackSSL_CTX_set_next_proto_select_cbSSL_CTX_set_next_protos_advertised_cbSSL_CTX_set_psk_client_callbackSSL_CTX_set_psk_server_callbackSSL_CTX_set_purposeSSL_CTX_set_quiet_shutdownSSL_CTX_set_session_id_contextSSL_CTX_set_srp_cb_argSSL_CTX_set_srp_client_pwd_callbackSSL_CTX_set_srp_passwordSSL_CTX_set_srp_strengthSSL_CTX_set_srp_usernameSSL_CTX_set_srp_username_callbackSSL_CTX_set_srp_verify_param_callbackSSL_CTX_set_ssl_versionSSL_CTX_set_timeoutSSL_CTX_set_tlsext_use_srtpSSL_CTX_set_tmp_dh_callbackSSL_CTX_set_tmp_ecdh_callbackSSL_CTX_set_tmp_rsa_callbackSSL_CTX_set_trustSSL_CTX_set_verifySSL_CTX_set_verify_depthSSL_CTX_use_PrivateKeySSL_CTX_use_PrivateKey_ASN1SSL_CTX_use_PrivateKey_fileSSL_CTX_use_RSAPrivateKeySSL_CTX_use_RSAPrivateKey_ASN1SSL_CTX_use_RSAPrivateKey_fileSSL_CTX_use_certificateSSL_CTX_use_certificate_ASN1SSL_CTX_use_certificate_chain_fileSSL_CTX_use_certificate_fileSSL_CTX_use_psk_identity_hintSSL_SESSION_freeSSL_SESSION_get0_peerSSL_SESSION_get_compress_idSSL_SESSION_get_ex_dataSSL_SESSION_get_ex_new_indexSSL_SESSION_get_idSSL_SESSION_get_timeSSL_SESSION_get_timeoutSSL_SESSION_newSSL_SESSION_printSSL_SESSION_print_fpSSL_SESSION_set1_id_contextSSL_SESSION_set_ex_dataSSL_SESSION_set_timeSSL_SESSION_set_timeoutSSL_SRP_CTX_freeSSL_SRP_CTX_initSSL_acceptSSL_add_client_CASSL_add_dir_cert_subjects_to_stackSSL_add_file_cert_subjects_to_stackSSL_alert_desc_stringSSL_alert_desc_string_longSSL_alert_type_stringSSL_alert_type_string_longSSL_cache_hitSSL_callback_ctrlSSL_check_private_keySSL_clearSSL_connectSSL_copy_session_idSSL_ctrlSSL_do_handshakeSSL_dupSSL_dup_CA_listSSL_export_keying_materialSSL_freeSSL_get0_next_proto_negotiatedSSL_get1_sessionSSL_get_SSL_CTXSSL_get_certificateSSL_get_cipher_listSSL_get_ciphersSSL_get_client_CA_listSSL_get_current_cipherSSL_get_current_compressionSSL_get_current_expansionSSL_get_default_timeoutSSL_get_errorSSL_get_ex_dataSSL_get_ex_data_X509_STORE_CTX_idxSSL_get_ex_new_indexSSL_get_fdSSL_get_finishedSSL_get_info_callbackSSL_get_peer_cert_chainSSL_get_peer_certificateSSL_get_peer_finishedSSL_get_privatekeySSL_get_psk_identitySSL_get_psk_identity_hintSSL_get_quiet_shutdownSSL_get_rbioSSL_get_read_aheadSSL_get_rfdSSL_get_selected_srtp_profileSSL_get_servernameSSL_get_servername_typeSSL_get_sessionSSL_get_shared_ciphersSSL_get_shutdownSSL_get_srp_NSSL_get_srp_gSSL_get_srp_userinfoSSL_get_srp_usernameSSL_get_srtp_profilesSSL_get_ssl_methodSSL_get_verify_callbackSSL_get_verify_depthSSL_get_verify_modeSSL_get_verify_resultSSL_get_versionSSL_get_wbioSSL_get_wfdSSL_has_matching_session_idSSL_library_initSSL_load_client_CA_fileSSL_load_error_stringsSSL_newSSL_peekSSL_pendingSSL_readSSL_renegotiateSSL_renegotiate_abbreviatedSSL_renegotiate_pendingSSL_rstate_stringSSL_rstate_string_longSSL_select_next_protoSSL_set1_paramSSL_set_SSL_CTXSSL_set_accept_stateSSL_set_bioSSL_set_cipher_listSSL_set_client_CA_listSSL_set_connect_stateSSL_set_debugSSL_set_ex_dataSSL_set_fdSSL_set_generate_session_idSSL_set_info_callbackSSL_set_msg_callbackSSL_set_psk_client_callbackSSL_set_psk_server_callbackSSL_set_purposeSSL_set_quiet_shutdownSSL_set_read_aheadSSL_set_rfdSSL_set_sessionSSL_set_session_id_contextSSL_set_session_secret_cbSSL_set_session_ticket_extSSL_set_session_ticket_ext_cbSSL_set_shutdownSSL_set_srp_server_paramSSL_set_srp_server_param_pwSSL_set_ssl_methodSSL_set_stateSSL_set_tlsext_use_srtpSSL_set_tmp_dh_callbackSSL_set_tmp_ecdh_callbackSSL_set_tmp_rsa_callbackSSL_set_trustSSL_set_verifySSL_set_verify_depthSSL_set_verify_resultSSL_set_wfdSSL_shutdownSSL_srp_server_param_with_usernameSSL_stateSSL_state_stringSSL_state_string_longSSL_use_PrivateKeySSL_use_PrivateKey_ASN1SSL_use_PrivateKey_fileSSL_use_RSAPrivateKeySSL_use_RSAPrivateKey_ASN1SSL_use_RSAPrivateKey_fileSSL_use_certificateSSL_use_certificate_ASN1SSL_use_certificate_fileSSL_use_psk_identity_hintSSL_versionSSL_wantSSL_writeSSLv23_client_methodSSLv23_methodSSLv23_server_methodSSLv2_client_methodSSLv2_methodSSLv2_server_methodSSLv3_client_methodSSLv3_methodSSLv3_server_methodTLSv1_1_client_methodTLSv1_1_methodTLSv1_1_server_methodTLSv1_2_client_methodTLSv1_2_methodTLSv1_2_server_methodTLSv1_client_methodTLSv1_methodTLSv1_server_methodd2i_SSL_SESSIONi2d_SSL_SESSIONssl2_ciphersssl3_ciphers( 0( 0 0(A0(A0 0('A0' 0(8' !088' 0'  0(8' !088' 0l' 0(8X'!088D'0,' 0(8'!088'0& 0(8&!088&0& 0(&A0& 0(|&!088h&0\&/@0H&0@04&1@0 &2@0 &3@0%4@0%50%60%70%80%90%:0%; 0t%<@0d%=0L%>@04%?@0%@@0 %A0$B0$C0$D0$E0$F0$g@0h$h0P$i08$j0 $k0 $l@0#m0#D#D# @# @#0t#0\#0D#0,#0#0 #A0"0"@0"0"A0"A0"A0"A0x"A0h"A0T"@@" @$"@" @!@! @!@! @|!@`! @H!@0! @!@ 0!@A0 @0 @@0 @0 @ 0 @A0x @0`  @@0H  @04    0   A0   0 @0 0 0A00@0p0` 0PA0<0(@00000@0@0@0l 0T!0<"0 #@@$@ %@@&@ '@( )@@l*@ L+@@,,@ @ -@@.@ @/@0 @1@@|2@ @p@PP$tl5666666666666666666666666666666666666666666666666\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\d(`(\(P0P0zp ..@t 0P0zp ..?<4$4d4555555555WWWWW @5_@p@4p $P`pPА`pp|hXL4 ؏ȏpX D00@P`Ўpt\<  ̍xh XH08@$P`p،̌xl`L4(ԋ 0@xP lP\P@@$`pȊ|\H0 ܉   |d0 L@@ 0P $` p  Ĉ   t T < $0   P0p \ 8`@Ԇ Ć   ` p `0 H(p`pЅ@ ąP `  dPL @(   Ԅ P  p L ,   ܃  0 `@ LP 8  ` p  ؂  p`L$pԁ  p X H 0 ܀ Ѐ 0 0  x`\@L@ @00P @` p  | h P 8  ~ ~ ~ ~~ t~ T~ H~,~~0}@}}0 }@ }d}X}eD}f,}g}h}j|k|l|m|n|o|pp|0`|1L|2@|L(|i||q{M{r{s{t{<{ul{v\{wL{x8{y {z {{z[z\z]z^z_z`za`z|Lz}0z~$zzzyyyyyyty\y@y$y yxxWxx3xlxPx8x4(xxw[wwwNw5dw=Dw>(wBwCv6vbvv`v@v(vvucuduuuuTduHu8uUuuetHtEttttltTt @t!t"t#s$s%s&s'|slsXsLs4s( s srrrrr|r`rDrf(rr7qqqqZqqhqPq8q$qqpppppKptpXpJpoooooS[DologXoDo4oonXn)nGnxnhnXn4n(nnmmmmxm`mHm4m mmlll8ll|lhl*TlO8lPlQlkVkkkpkYLk8kkkhjjijjjk\jl PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXP 0!0<00011b235344466;77C88i:::E;m;;b>>?O?? L0h011h222T34 4536h6l6p6t6x6|666666!7<7789v<<==>>0d 0f00D1[111(2Q2233J444L5555>667^77@88t9:H:8;?;<B>?@\00P1u111w222334244444g77I888];;;;;;;;;f??%???P@0011124 5?6m67/7j7777999:}:{;;[==>^???`H0>01?1n11>2x223U3u346X7388#949T9;+<<(==:>f>>>>y?pd80000(1_11;2222Y3}33:4/5d55)7b77889.9:1:Y:::;J;r;;>>?h?0'0X00011F22278^8{88 9{99Z:a:l2`22222222333 33333 3$3(3,30314O44566a6d7=99":q::J;;;+?4?M?c?\0p000c11334K4444I55K6667777$8z8899:b:_;x;;;;<==>2>O>>?P4000o11162L22 3445A5n55A666.7[77 8889&:Z;;.>LS000N112<3333434\445057888R889r999::::;<<==3334T4X4\4`4d4h4l4p4t4x4|44444455677j9997:W:::::F;_;};;;N>> >>>>> >$>(>,>0>4>8>>>>D?H?L?P?T????h90Z00000-1j11"333R334 44444 4$4(4,4044484<4@4D4H4L4445555555555*6=>[?\$1[1111i2222b34]778C9K::u;;[<<===(>,>0>4>8><>@>D>H>L>P>T>X>\>`>1???<12m34,4t44U66L778B9::9<<<<<< ==>?,0D1:257T778@8V8888O9]9{;m=? T1+252h2r2t334C4M444D5 6678&999;;;;;;;;;;;'?0<K022222233g347a7789:;<===> ?|?@ 01z222344!556e6667Q8a8|88888888 9!919A9\9i9{991:: ;;;;; ;$;(;,;0;4;8;<;@;D;H;L;P;T;X;\;`;d;h;l;p;;P$0w14k46{:;=>>?T???`4124566D6H6L6P6T6X678899;*<p001I4[44459b::;;;9?$?d061O111[2222373=3G33356[78{8;:::;;;<<<====0>V>> ?'??????????p000 00000 0$0(0,0004080<0@0D0H0L0P0T0001"2v22;4485555667y77'8d889%9:1;F_>p>H06111#5Z5566>>>>>>>>>>>>>>>>>>>>>?H001E2334556K7y777889V999::;<<??<007x7777777777777888 88989.>>r?,j3l44667k:: ;;;<<<<<<>42338999:E:[:::@;N;;;:<^<<=h=>\t0~00E112445 5555555J6g6q68A9::}:;<;;;;;/<<D>>>?@z01[3333T6+858h8r8X99;;<<<<<>>>>>_???X0111 2w2}2233-444355555O666667779y:);^>>>>?`?? X0,031:1222222222222222333 33333 3$3(3,34)56678.8s;#<;<0@182q2234455555 66%6.6567#9;<=>l>???@d000111C233'4444 6$6(6,6064686<6@6D6H6L6P666777788_8{8888899 :B:;P0$050H0W0i0x0000000G1d1 222]22-3Y3y333344445c55~66677 8O9,:F::::;>>?`\A1w1o2|33x5566E6J6u6z6666777W888+9H9{9993:~:W;;;;;<==>h>>>9?p 00111112 2222)2.282=2G2L2V2[2e2j2t2y2222222222222222333'343A3S3\3f3s3}333333333344)4<4N4a4n4}44445a5}5555566+6>6Q666666677?7M7^778M8888888888888888,9=999/:9:O:b:v:::::::;*;F;Q;g;z;;;;#=50R0u222S4}455::@;L;c;`<<<<===-=M=T=g=t==========>!>*>6>=>E>O>Y>c>m>}>>>>>>>>> ??(?/?6?=?D?m?t?{?????????????0&0?0e0000000000000000L1P1T1X1\1`1d111111111222223<3^3334"4:4A4F4L4R4X4^4d4j4p4v4|444444444444444445 5555#5)5/555;5A5G5M5S5Y5_5e5k5q5w555555555555556 6666!6'6-63696?6E6K6Q6W6]66666666666666666666667 7777"7(7.747:7@7F7L7R7X7u7{777777777777777777777777788888888888888888888888888888899999999999::: ::::: :$:(:,:0:4:8:<;@;D;H;L;P;T;X;\;`;d;h;l;p;t;x;|;;;;;;;;;;;;;;;;;;<<<<="=:=A=F=L=R=X=^=d=j=p=v=|=================> >>>>#>)>/>5>;>A>G>M>S>Y>_>e>>>>>>>>>>>>>>>>>? ????!?'?-?3?9?b?i?n?t?z???????????????????????(0 0000"0(0<0B0H0P0T0X0\0`0d0h0l0p0t0x0|00000000 1$1(1,1014181<1@1D1H1L1P1T1X1\1`1d1h1l1p1t1x1|11111111`2d2h2l2p2t2x2|222222222222223333333333333333333333444 44444 4$4 555=5F5M5u5|555555555555555555555556 6666#6)6/656<6@6D6H6L6P6T6X6\6`6d6h6l6p6t6x6|666666666666666E7L7Q7W7]7c7i7o7u7{777777777777777777777778 88888 8$8(8,8084888<8@8D8H8L8P8T8X8\8`8d8h8l8p8t8x8|88899%9+9R99?:v::;w;;>?E???L0l001E111 2y223r334F4r44#555)6o6663777A88819w9;:557844555+595G5S5Z5`5555556*6F6i666667 77?7E7[7{7777.8H8i888889::#:-:B:L:V:`:::::::;;*;:<>>>>??? ?F?M?L0011$3(3,3034383<3@3D3H3L3P3T3X3\3`3d3h3l3p3r45a6s6~6:::k;?u013394x44c5(626K6U6p6657778 8888"8(8.848:8@8F8L8R8X8^8d8j8p8v8|888888888888888888888899 9999$9*90969<9B9H9N9T9Z9`9f9l9r9x9~9999999999999999999999::::: :&:,:2:8:>:D:J:P:V:\:b:h:n:t:z:::::::::::::::::::::::; ;;;;";(;.;4;:;@;F;L;R;X;^;d;j;p;v;|;;;;;;;;;;;;;;;;;;;;;;<< <<<<$<*<0<6<<=D=J=P=V=\=b=h=n=t=z=======================> >>>>">(>.>4>:>@>F>L>R>X>^>d>j>p>v>|>>>>>>>>>>>>>>>>>>>>>>?? ????$?*?0?6?>> >>>>> >$>(>,>0>4>8><>@>D>H>L>P>T>X>d>h>l>p>t>x>|>>>>>>>>>>>>>>>>>>>>>>?????0000 00000 0$0(0,0004080<0@0D0H0L0P0T0X0d0h0l0p0t0x0|000000000000000000000000000111 11111 1$1(1,1014181<1@1D1H1L1P1T1X1848d8888$9T9999:D:t:::;4;d;;;;$4>d>>>>$?T????@D0D0t000141d1111$2T22223D3t333444d4444$5T511$2(2222233040d0000$1T11112D2t222343d3333$4T44445D5t555646d6666$7T77778D8t888949d9999$:T::::;D;t;;;<4D>t>>>?4?d????$0T00001D1t111242d2222$3T33334D4t444545d5555$6T66667D7t777848d8888$9T9999:@:D:H:L:P:T:\:`:h:p:t::::::::::;;;;;T >>>$>,>4><>D>L>T>\>d>l>t>|>>>>>>>>>>>>>>>>>? ???$?,?4?/dev/null || echo "-lcurl"` # adjust linker flags for gdc command line LIBS=`echo "$LIBS" | sed 's/^-L/-L-L/; s/ -L/ -L-L/g; s/^-l/-L-l/; s/ -l/ -L-l/g'` echo Generating version file... GITVER=$(git describe) || GITVER=unknown echo "module dub.version_;" > source/dub/version_.d echo "enum dubVersion = \"$GITVER\";" >> source/dub/version_.d echo Running $GDC... $GDC -obin/dub -lcurl -w -fversion=DubUseCurl -fversion=DubApplication -Isource $* $LIBS @build-files.txt echo DUB has been built as bin/dub. echo echo You may want to run echo sudo ln -s $(pwd)/bin/dub /usr/local/bin echo now. dub-1.19.0/build.cmd000066400000000000000000000010421360435400500141350ustar00rootroot00000000000000@if "%DC%"=="" set DC=dmd @echo Generating version file... @set GITVER=unknown @for /f %%i in ('git describe') do @set GITVER=%%i @echo module dub.version_; > source\dub\version_.d @echo enum dubVersion = "%GITVER%"; >> source\dub\version_.d @echo Executing %DC%... @%DC% -ofbin\dub.exe -g -O -w -version=DubUseCurl -version=DubApplication -Isource %* @build-files.txt @if errorlevel 1 exit /b 1 @echo DUB has been built. You probably also want to add the following entry to your @echo PATH environment variable: @echo %CD%\bin dub-1.19.0/build.sh000077500000000000000000000021261360435400500140130ustar00rootroot00000000000000#!/usr/bin/env bash set -e if [ "$DMD" = "" ]; then if [ ! "$DC" = "" ]; then # backwards compatibility with DC DMD=$DC else command -v gdmd >/dev/null 2>&1 && DMD=gdmd || true command -v ldmd2 >/dev/null 2>&1 && DMD=ldmd2 || true command -v dmd >/dev/null 2>&1 && DMD=dmd || true fi fi if [ "$DMD" = "" ]; then echo >&2 "Failed to detect D compiler. Use DMD=... to set a dmd compatible binary manually." exit 1 fi if [ "$GITVER" = "" ]; then GITVER=$(git describe) || echo "Could not determine a version with git." fi if [ "$GITVER" != "" ]; then echo Generating version file... echo "module dub.version_;" > source/dub/version_.d echo "enum dubVersion = \"$GITVER\";" >> source/dub/version_.d else echo Using existing version file. fi # For OSX compatibility >= 10.8 MACOSX_DEPLOYMENT_TARGET=10.8 echo Running $DMD... DFLAGS="${DFLAGS:--g -O -w}" $DMD -ofbin/dub $DFLAGS -version=DubUseCurl -version=DubApplication -Isource $* @build-files.txt bin/dub --version echo DUB has been built as bin/dub. echo echo You may want to run echo sudo ln -s $(pwd)/bin/dub /usr/local/bin echo now. dub-1.19.0/changelog/000077500000000000000000000000001360435400500143035ustar00rootroot00000000000000dub-1.19.0/changelog/README.md000066400000000000000000000027201360435400500155630ustar00rootroot00000000000000This directory will get copied to dlang.org and cleared when master gets merged into stable prior to a new release. How to add a new changelog entry to the pending changelog? ========================================================== Create a new file in the `changelog` folder. It should end with `.dd` and look similar to a git commit message. The first line represents the title of the change. After an empty line follows the long description: ``` My fancy title of the new feature A long description of the new feature in `std.range`. It can be followed by an example: ------- import std.range : padLeft, padRight; import std.algorithm.comparison : equal; assert([1, 2, 3, 4, 5].padLeft(0, 7).equal([0, 0, 1, 2, 3, 4, 5])); assert("Hello World!".padRight('!', 15).equal("Hello World!!!!")); ------- and links to the documentation, e.g. $(REF drop, std, range) or $(REF_ALTTEXT a custom name for the function, drop, std, range). Links to the spec can look like this $(LINK2 $(ROOT_DIR)spec/module.html, this) and of course you can link to other $(LINK2 https://forum.dlang.org/, external resources). ``` The title can't contain links (it's already one). For more infos, see the [Ddoc spec](https://dlang.org/spec/ddoc.html). Preview changes --------------- If you have cloned the [tools](https://github.com/dlang/tools) and [dlang.org](https://github.com/dlang/dlang.org) repo, you can preview the changelog with: ``` make -C ../dlang.org -f posix.mak pending_changelog ``` dub-1.19.0/dub.sdl000066400000000000000000000017211360435400500136330ustar00rootroot00000000000000name "dub" description "Package manager for D packages" authors "Sönke Ludwig" "Martin Nowak" "Matthias Dondorff" "Sebastian Wilzbach" \ "more than 80 contributors total" copyright "Copyright © 2012-2016 rejectedsoftware e.K., Copyright © 2012-2014 Matthias Dondorff" license "MIT" targetPath "bin" configuration "application" { targetType "executable" mainSourceFile "source/app.d" libs "curl" versions "DubUseCurl" "DubApplication" } configuration "library" { targetType "library" excludedSourceFiles "source/app.d" copyFiles "bin/libcurl.dll" "bin/libeay32.dll" "bin/ssleay32.dll" platform="windows" versions "DubUseCurl" } configuration "library-nonet" { dependency "vibe-d:http" version=">=0.7.30 <=0.9.0" optional=true targetType "library" excludedSourceFiles "source/app.d" } configuration "dynamic-library-nonet" { dependency "vibe-d:http" version=">=0.7.30 <=0.9.0" optional=true targetType "dynamicLibrary" excludedSourceFiles "source/app.d" } dub-1.19.0/dub.selections.json000066400000000000000000000006221360435400500161700ustar00rootroot00000000000000{ "fileVersion": 1, "versions": { "botan": "1.12.10", "botan-math": "1.0.3", "diet-ng": "1.6.0", "eventcore": "0.8.48", "libasync": "0.8.4", "libev": "5.0.0+4.04", "libevent": "2.0.2+2.0.16", "memutils": "0.4.13", "mir-linux-kernel": "1.0.1", "openssl": "1.1.6+1.0.1g", "stdx-allocator": "2.77.5", "taggedalgebraic": "0.11.8", "vibe-core": "1.8.1", "vibe-d": "0.8.6" } } dub-1.19.0/examples/000077500000000000000000000000001360435400500141725ustar00rootroot00000000000000dub-1.19.0/examples/app-sdl/000077500000000000000000000000001360435400500155325ustar00rootroot00000000000000dub-1.19.0/examples/app-sdl/dub.sdl000066400000000000000000000000721360435400500170070ustar00rootroot00000000000000name "app-example"; description "A simple D application"; dub-1.19.0/examples/app-sdl/source/000077500000000000000000000000001360435400500170325ustar00rootroot00000000000000dub-1.19.0/examples/app-sdl/source/app.d000066400000000000000000000000761360435400500177620ustar00rootroot00000000000000import std.stdio; void main() { writeln("Hello, World."); } dub-1.19.0/examples/app/000077500000000000000000000000001360435400500147525ustar00rootroot00000000000000dub-1.19.0/examples/app/dub.json000066400000000000000000000001051360435400500164130ustar00rootroot00000000000000{ "name": "app-example", "description": "A simple D application" } dub-1.19.0/examples/app/source/000077500000000000000000000000001360435400500162525ustar00rootroot00000000000000dub-1.19.0/examples/app/source/app.d000066400000000000000000000000761360435400500172020ustar00rootroot00000000000000import std.stdio; void main() { writeln("Hello, World."); } dub-1.19.0/examples/generated-sources/000077500000000000000000000000001360435400500176115ustar00rootroot00000000000000dub-1.19.0/examples/generated-sources/dub.json000066400000000000000000000003041360435400500212530ustar00rootroot00000000000000{ "name": "generated-sources", "description": "Example of using pre generate commands to generate source code.", "preGenerateCommands": [ "echo int fun() { return 42; } > source/test.d" ] } dub-1.19.0/examples/generated-sources/source/000077500000000000000000000000001360435400500211115ustar00rootroot00000000000000dub-1.19.0/examples/generated-sources/source/app.d000066400000000000000000000001201360435400500220270ustar00rootroot00000000000000import std.stdio; import test; void main() { writefln("Result: %s", fun()); } dub-1.19.0/examples/header-lib/000077500000000000000000000000001360435400500161665ustar00rootroot00000000000000dub-1.19.0/examples/header-lib/dub.json000066400000000000000000000002361360435400500176340ustar00rootroot00000000000000{ "name": "header-lib-example", "description": "A simple D header library (C binding to libmylib.so)", "targetType": "sourceLibrary", "libs": ["mylib"] } dub-1.19.0/examples/header-lib/import/000077500000000000000000000000001360435400500175005ustar00rootroot00000000000000dub-1.19.0/examples/header-lib/import/mylib.d000066400000000000000000000000461360435400500207610ustar00rootroot00000000000000module mylib; extern(C) void test(); dub-1.19.0/examples/lib-user/000077500000000000000000000000001360435400500157145ustar00rootroot00000000000000dub-1.19.0/examples/lib-user/dub.json000066400000000000000000000002641360435400500173630ustar00rootroot00000000000000{ "name": "lib-user-example", "description": "An application using a local library dependency", "dependencies": { "lib-example": {"version": "~master", "path": "../lib"} } } dub-1.19.0/examples/lib-user/source/000077500000000000000000000000001360435400500172145ustar00rootroot00000000000000dub-1.19.0/examples/lib-user/source/app.d000066400000000000000000000000461360435400500201410ustar00rootroot00000000000000import lib; void main() { test(); } dub-1.19.0/examples/lib/000077500000000000000000000000001360435400500147405ustar00rootroot00000000000000dub-1.19.0/examples/lib/dub.json000066400000000000000000000001331360435400500164020ustar00rootroot00000000000000{ "name": "lib-example", "description": "A simple D library", "targetType": "library" } dub-1.19.0/examples/lib/source/000077500000000000000000000000001360435400500162405ustar00rootroot00000000000000dub-1.19.0/examples/lib/source/lib.d000066400000000000000000000001131360435400500171460ustar00rootroot00000000000000module lib; import std.stdio; void test() { writeln("Hello, World."); } dub-1.19.0/examples/mixed/000077500000000000000000000000001360435400500153005ustar00rootroot00000000000000dub-1.19.0/examples/mixed/dub.json000066400000000000000000000001471360435400500167470ustar00rootroot00000000000000{ "name": "mixed-example", "description": "A package usable as both, an application and a library" } dub-1.19.0/examples/mixed/source/000077500000000000000000000000001360435400500166005ustar00rootroot00000000000000dub-1.19.0/examples/mixed/source/app.d000066400000000000000000000000631360435400500175240ustar00rootroot00000000000000module app; import lib; void main() { test(); } dub-1.19.0/examples/mixed/source/lib.d000066400000000000000000000001131360435400500175060ustar00rootroot00000000000000module lib; import std.stdio; void test() { writeln("Hello, World!"); } dub-1.19.0/examples/vibed-main/000077500000000000000000000000001360435400500162055ustar00rootroot00000000000000dub-1.19.0/examples/vibed-main/dub.json000066400000000000000000000002671360435400500176570ustar00rootroot00000000000000{ "name": "vibed-main-example", "description": "A project using vibe.d and a custom main() function", "dependencies": { "vibe-d": "~master" }, "versions": ["VibeCustomMain"] } dub-1.19.0/examples/vibed-main/source/000077500000000000000000000000001360435400500175055ustar00rootroot00000000000000dub-1.19.0/examples/vibed-main/source/app.d000066400000000000000000000003451360435400500204340ustar00rootroot00000000000000import vibe.vibe; void main() { listenHTTP(new HTTPServerSettings, &handleRequest); lowerPrivileges(); runEventLoop(); } void handleRequest(HTTPServerRequest req, HTTPServerResponse res) { res.writeBody("Hello, World!"); } dub-1.19.0/examples/vibed/000077500000000000000000000000001360435400500152635ustar00rootroot00000000000000dub-1.19.0/examples/vibed/dub.json000066400000000000000000000001641360435400500167310ustar00rootroot00000000000000{ "name": "vibed-example", "description": "A project using vibe.d", "dependencies": { "vibe-d": "~master" } } dub-1.19.0/examples/vibed/source/000077500000000000000000000000001360435400500165635ustar00rootroot00000000000000dub-1.19.0/examples/vibed/source/app.d000066400000000000000000000003061360435400500175070ustar00rootroot00000000000000import vibe.d; shared static this() { listenHTTP(new HTTPServerSettings, &handleRequest); } void handleRequest(HTTPServerRequest req, HTTPServerResponse res) { res.writeBody("Hello, World!"); } dub-1.19.0/release-windows.sh000077500000000000000000000007411360435400500160250ustar00rootroot00000000000000#!/usr/bin/env bash # Build the Windows binaries under Linux set -eux -o pipefail BIN_NAME=dub # Allow the script to be run from anywhere DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $DIR source setup-ldc-windows.sh # Run LDC with cross-compilation archiveName="$BIN_NAME-$VERSION-$OS-$ARCH_SUFFIX.zip" echo "Building $archiveName" mkdir -p bin DC=ldmd2 DFLAGS="-release" ./build.sh cd bin mv "${BIN_NAME}" "${BIN_NAME}.exe" zip "$archiveName" "${BIN_NAME}.exe" dub-1.19.0/release.sh000077500000000000000000000016051360435400500143350ustar00rootroot00000000000000#!/usr/bin/env bash set -eux -o pipefail VERSION=$(git describe --abbrev=0 --tags) ARCH="${ARCH:-64}" CUSTOM_FLAGS=() unameOut="$(uname -s)" case "$unameOut" in Linux*) OS=linux CUSTOM_FLAGS+=("-L--export-dynamic") ;; Darwin*) OS=osx CUSTOM_FLAGS+=("-L-dead_strip") ;; *) echo "Unknown OS: $unameOut"; exit 1 esac if [[ $(basename "$DMD") =~ ldmd.* ]] ; then CUSTOM_FLAGS+=("-flto=full") # ld.gold is required on Linux if [ ${OS:-} == "linux" ] ; then CUSTOM_FLAGS+=("-linker=gold") fi fi case "$ARCH" in 64) ARCH_SUFFIX="x86_64";; 32) ARCH_SUFFIX="x86";; *) echo "Unknown ARCH: $ARCH"; exit 1 esac archiveName="dub-$VERSION-$OS-$ARCH_SUFFIX.tar.gz" echo "Building $archiveName" DFLAGS="-release -m$ARCH ${CUSTOM_FLAGS[@]}" DMD="$(command -v $DMD)" ./build.sh tar cvfz "bin/$archiveName" -C bin dub dub-1.19.0/scripts/000077500000000000000000000000001360435400500140435ustar00rootroot00000000000000dub-1.19.0/scripts/bash-completion/000077500000000000000000000000001360435400500171275ustar00rootroot00000000000000dub-1.19.0/scripts/bash-completion/dub.bash000066400000000000000000000036661360435400500205530ustar00rootroot00000000000000# dub(1) completion -*- shell-script -*- _dub() { local cur prev words cword split _init_completion -s || return local creation_commands creation_commands='init run build test generate describe clean dustmite' local management_commands management_commands='fetch remove upgrade add-path remove-path add-local remove-local list add-override remove-override list-overrides clean-caches' case "$prev" in -h|--help) return 0 ;; esac $split && return 0 # Use -h -v -q because lack of comma separation between -h and --help local common_options common_options='-h -v -q'; local packages packages=$(dub list| awk '/^[[:space:]]+/ { print $1 }') if [[ $cword -eq 1 ]] ; then # if one argument given if [[ "$cur" == -* ]]; then COMPREPLY=( $( compgen -W '$common_options $( _parse_help "$1" )' -- "$cur" ) ) else COMPREPLY=( $( compgen -W "$creation_commands $management_commands" -- "$cur" ) ) fi else local command=${words[1]}; # use $prev instead? local specific_options specific_options=$( "$1" $command --help 2>/dev/null | _parse_help - ) case $command in init | add-path | remove-path | add-local | remove-local | dustmite ) COMPREPLY=( $( compgen -d -W '$common_options $specific_options' -- "$cur" ) ) ;; run | build | test | generate | describe | clean | upgrade | add-override | remove-override ) COMPREPLY=( $( compgen -W '$packages $common_options $specific_options' -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W '$common_options $specific_options' -- "$cur" ) ) ;; esac fi [[ $COMPREPLY == *= ]] && compopt -o nospace return # NOTE: Disabled for now # _filedir } && complete -F _dub dub dub-1.19.0/scripts/fish-completion/000077500000000000000000000000001360435400500171435ustar00rootroot00000000000000dub-1.19.0/scripts/fish-completion/dub.fish000066400000000000000000000162671360435400500206040ustar00rootroot00000000000000# # Completions for the dub command # # # Subcommands # # Package creation complete -c dub -n '__fish_use_subcommand' -x -a init -d 'Initializes an empty package skeleton' # Build, test, and run complete -c dub -n '__fish_use_subcommand' -x -a run -d 'Builds and runs a package' complete -c dub -n '__fish_use_subcommand' -x -a build -d 'Builds a package' complete -c dub -n '__fish_use_subcommand' -x -a test -d 'Executes the tests of the selected package' complete -c dub -n '__fish_use_subcommand' -x -a generate -d 'Generates project files using the specified generator' complete -c dub -n '__fish_use_subcommand' -x -a describe -d 'Prints a JSON description of the project and its dependencies' complete -c dub -n '__fish_use_subcommand' -x -a clean -d 'Removes intermediate build files and cached build results' complete -c dub -n '__fish_use_subcommand' -x -a dustmite -d 'Create reduced test cases for build errors' # Package management complete -c dub -n '__fish_use_subcommand' -x -a fetch -d 'Manually retrieves and caches a package' complete -c dub -n '__fish_use_subcommand' -x -a remove -d 'Removes a cached package' complete -c dub -n '__fish_use_subcommand' -x -a upgrade -d 'Forces an upgrade of all dependencies' complete -c dub -n '__fish_use_subcommand' -x -a add-path -d 'Adds a default package search path' complete -c dub -n '__fish_use_subcommand' -x -a remove-path -d 'Removes a package search path' complete -c dub -n '__fish_use_subcommand' -x -a add-local -d 'Adds a local package directory' complete -c dub -n '__fish_use_subcommand' -x -a remove-local -d 'Removes a local package directory' complete -c dub -n '__fish_use_subcommand' -x -a list -d 'Prints a list of all local packages dub is aware of' complete -c dub -n '__fish_use_subcommand' -x -a add-override -d 'Adds a new package override' complete -c dub -n '__fish_use_subcommand' -x -a remove-override -d 'Removes an existing package override' complete -c dub -n '__fish_use_subcommand' -x -a list-overrides -d 'Prints a list of all local package overrides' complete -c dub -n '__fish_use_subcommand' -x -a clean-caches -d 'Removes cached metadata' # # Subcommand options # for cmd in run build complete -c dub -n "contains '$cmd' (commandline -poc)" -l rdmd -d "Use rdmd" end for cmd in run build test complete -c dub -n "contains '$cmd' (commandline -poc)" -s f -l force -d "Force recompilation" end for cmd in run complete -c dub -n "contains '$cmd' (commandline -poc)" -l temp-build -d "Build in temp folder" end for cmd in run build test generate describe dustmite complete -c dub -n "contains '$cmd' (commandline -poc)" -s c -l config -r -d "Build configuration" complete -c dub -n "contains '$cmd' (commandline -poc)" -s a -l arch -r -d "Force architecture" complete -c dub -n "contains '$cmd' (commandline -poc)" -s d -l debug -r -d "Debug identifier" complete -c dub -n "contains '$cmd' (commandline -poc)" -l nodeps -d "No dependency check" complete -c dub -n "contains '$cmd' (commandline -poc)" -s b -l build -u -x -d "Build type" -a "debug plain release release-debug release-nobounds unittest profile profile-gc docs ddox cov unittest-cov syntax" complete -c dub -n "contains '$cmd' (commandline -poc)" -l build-mode -x -d "How compiler & linker are invoked" -a "separate allAtOnce singleFile" complete -c dub -n "contains '$cmd' (commandline -poc)" -l compiler -x -d "Compiler binary" -a "dmd gdc ldc gdmd ldmd" end for cmd in run build test generate describe dustmite fetch remove upgrade complete -c dub -n "contains '$cmd' (commandline -poc)" -l force-remove -x -d "Force deletion" end for cmd in run build dustmite complete -c dub -n "contains '$cmd' (commandline -poc)" -l combined -d "Build project in single compiler run" end for cmd in run build test generate complete -c dub -n "contains '$cmd' (commandline -poc)" -l print-builds -d "Print list of build types" end for cmd in run build generate complete -c dub -n "contains '$cmd' (commandline -poc)" -l print-configs -d "Print list of configurations" complete -c dub -n "contains '$cmd' (commandline -poc)" -l print-platform -d "Print build platform identifiers" end for cmd in build dustmite fetch remove complete -c dub -n "contains '$cmd' (commandline -poc)" -x -d "Package" -a '(dub list | awk \'/^[[:space:]]+/ { print $1 }\' | cut -f 3 -d " ")' end for cmd in clean complete -c dub -n "contains '$cmd' (commandline -poc)" -l all-packages -d "Clean all known packages" end for cmd in dustmite complete -c dub -n "contains '$cmd' (commandline -poc)" -l compiler-status -x -d "Expected compiler status code" complete -c dub -n "contains '$cmd' (commandline -poc)" -l compiler-regex -x -d "Compiler output regular expression" complete -c dub -n "contains '$cmd' (commandline -poc)" -l linker-status -x -d "Expected linker status code" complete -c dub -n "contains '$cmd' (commandline -poc)" -l linker-regex -x -d "Linker output regular expression" complete -c dub -n "contains '$cmd' (commandline -poc)" -l program-status -x -d "Expected program status code" complete -c dub -n "contains '$cmd' (commandline -poc)" -l program-regex -x -d "Program output regular expression" complete -c dub -n "contains '$cmd' (commandline -poc)" -l test-package -x -d "Perform a test run" end for cmd in fetch remove complete -c dub -n "contains '$cmd' (commandline -poc)" -l version -r -d "Version to use" complete -c dub -n "contains '$cmd' (commandline -poc)" -l system -d "Deprecated" complete -c dub -n "contains '$cmd' (commandline -poc)" -l local -d "Deprecated" end for cmd in upgrade complete -c dub -n "contains '$cmd' (commandline -poc)" -l prerelease -d "Use latest pre-release version" complete -c dub -n "contains '$cmd' (commandline -poc)" -l verify -d "Update if successful build" complete -c dub -n "contains '$cmd' (commandline -poc)" -l missing-only -d "Update dependencies without a selected version" end for cmd in add-path remove-path add-local remove-local add-override remove-override complete -c dub -n "contains '$cmd' (commandline -poc)" -l system -d "System-wide" end # Common options complete -c dub -s h -l help -d "Display help" complete -c dub -l root -r -d "Path to operate in" complete -c dub -l registry -r -d "Use DUB registry URL" complete -c dub -l annotate -d "Just print actions" complete -c dub -s v -l verbose -d "Print diagnostic output" complete -c dub -l vverbose -d "Print debug output" complete -c dub -s q -l quiet -d "Only print warnings and errors" complete -c dub -l vquiet -d "Print no messages" complete -c dub -l cache -x -d "Use cache location" -a "local system user" dub-1.19.0/scripts/man/000077500000000000000000000000001360435400500146165ustar00rootroot00000000000000dub-1.19.0/scripts/man/.gitignore000066400000000000000000000000151360435400500166020ustar00rootroot00000000000000*.1 /gen_man dub-1.19.0/scripts/man/README.md000066400000000000000000000001361360435400500160750ustar00rootroot000000000000001) Build -------- ```shell ./gen_man.d ``` 2) Preview ---------- ```shell man -l dub.1 ``` dub-1.19.0/scripts/man/gen_man.d000077500000000000000000000112121360435400500163670ustar00rootroot00000000000000#!/usr/bin/env dub /+dub.sdl: dependency "dub" path="../.." +/ import std.algorithm, std.conv, std.format, std.path, std.range, std.stdio; import dub.commandline; string italic(string w) { return `\fI` ~ w ~ `\fR`; } string bold(string w) { return `\fB` ~ w ~ `\fR`; } string header(string heading) { return ".SH " ~ heading; } string br(string s) { return ".BR " ~ s; } struct Config { import std.datetime; SysTime date; static Config init(){ import std.process : environment; Config config; config.date = Clock.currTime; auto diffable = environment.get("DIFFABLE", "0"); if (diffable == "1") config.date = SysTime(DateTime(2018, 01, 01)); config.cwd = __FILE_FULL_PATH__.dirName; return config; } string cwd; } void writeHeader(ref File manFile, string manName, const Config config) { static immutable manHeader = `.TH %s 1 "%s" "The D Language Foundation" "The D Language Foundation" .SH NAME`; manFile.writefln(manHeader, manName, config.date.toISOExtString.take(10)); } void writeFooter(ref File manFile, string seeAlso, const Config config) { static immutable manFooter = `.SH FILES \fIdub\&.sdl\fR, \fIdub\&.json\fR .SH AUTHOR Copyright (c) 1999-%s by The D Language Foundation .SH "ONLINE DOCUMENTATION" .UR http://code.dlang.org/docs/commandline .UE http://code.dlang.org/docs/commandline .SH "SEE ALSO" %s`; manFile.writefln(manFooter, config.date.year, seeAlso); } void writeMainManFile(CommandArgs args, CommandGroup[] commands, string fileName, const Config config) { auto manFile = File(config.cwd.buildPath(fileName), "w"); manFile.writeHeader("DUB", config); auto seeAlso = ["dmd(1)".br, "rdmd(1)"].joiner("\n").to!string; scope(exit) manFile.writeFooter(seeAlso, config); alias writeln = (m) => manFile.writeln(m); writeln(`dub \- Package and build management system for D`); writeln("SYNOPSIS".header); writeln(`.B dub [\-\-version] [\fICOMMAND\fR] [\fIOPTIONS\&.\&.\&.\fR] [\-\- [\fIAPPLICATION ARGUMENTS\&.\&.\&.\fR]]`); writeln("DESCRIPTION".header); writeln(`Manages the DUB project in the current directory\&. DUB can serve as a build system and a package manager, automatically keeping track of project's dependencies \- both downloading them and linking them into the application.`); writeln(".SH COMMANDS"); foreach (grp; commands) { foreach (cmd; grp.commands) { writeln(".TP"); writeln(cmd.name.bold); writeln(cmd.helpText.joiner("\n")); } } writeln("COMMON OPTIONS".header); args.writeArgs(manFile); } string highlightArguments(string args) { import std.regex : regex, replaceAll; static auto re = regex("<([^>]*)>"); static const reReplacement = "<%s>".format(`$1`.italic); return args.replaceAll(re, reReplacement); } void writeArgs(CommandArgs args, ref File manFile) { alias write = (m) => manFile.write(m); foreach (arg; args.recognizedArgs) { auto names = arg.names.split("|"); assert(names.length == 1 || names.length == 2); string sarg = names[0].length == 1 ? names[0] : null; string larg = names[0].length > 1 ? names[0] : names.length > 1 ? names[1] : null; write(".IP "); if (sarg !is null) { write("-%s".format(sarg)); if (larg !is null) write(", "); } if (larg !is null) { write("--%s".format(larg)); if (!arg.defaultValue.peek!bool) write("=VALUE"); } manFile.writeln; manFile.writeln(arg.helpText.join("\n")); } } void writeManFile(Command command, const Config config) { import std.uni : toUpper; auto args = new CommandArgs(null); command.prepare(args); string fileName = format("dub-%s.1", command.name); auto manFile = File(config.cwd.buildPath(fileName), "w"); auto manName = format("DUB-%s", command.name).toUpper; manFile.writeHeader(manName, config); static immutable seeAlso = ["dmd(1)".br, "dub(1)"].joiner("\n").to!string; scope(exit) manFile.writeFooter(seeAlso, config); alias writeln = (m) => manFile.writeln(m); writeln(`dub \- Package and build management system for D`); writeln("SYNOPSIS".header); writeln("dub %s".format(command.name).bold); writeln(command.argumentsPattern.highlightArguments); writeln(`OPTIONS\&.\&.\&.`.italic); if (command.acceptsAppArgs) { writeln("[-- <%s>]".format("application arguments...".italic)); } writeln("DESCRIPTION".header); writeln(command.helpText.joiner("\n\n")); writeln("OPTIONS".header); args.writeArgs(manFile); } void main() { Config config = Config.init; auto commands = getCommands(); // main dub.1 { CommonOptions options; auto args = new CommandArgs(null); options.prepare(args); args.writeMainManFile(commands, "dub.1", config); } // options for each specific command foreach (cmd; commands.map!(a => a.commands).joiner) { cmd.writeManFile(config); } } dub-1.19.0/scripts/rpm-package/000077500000000000000000000000001360435400500162325ustar00rootroot00000000000000dub-1.19.0/scripts/rpm-package/dub.spec000066400000000000000000000017611360435400500176650ustar00rootroot00000000000000## command is: # rpmbuild -ba dub.spec --define 'ver 0.9.21' --define 'rel 0.rc.3' # rpm file will be in ./dub*.rpm # if built on a i386 platform, rpm file will be in ~/rpmbuild/RPMS/i386/dub*.rpm Name: dub Summary: Package manager and meta build tool for the D programming language Vendor: rejectedsoftware e.K. Version: %{ver} Release: %{rel} License: MIT Group: Applications/Programming #Source: dub.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id} -u -n) URL: http://code.dlang.org BuildRequires: tar %description Package Manager for the D Programming language %prep #echo prep #tar -xf %{_sourcedir}/dub.tar.gz %build echo build cd %{srcpath} && ./build.sh %install echo install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT%{_bindir}/ cp %{srcpath}/bin/dub $RPM_BUILD_ROOT%{_bindir}/ %files # # list all files that need to be copied here # %defattr(755,root,root,-) /usr/bin/dub %clean cp $RPM_BUILD_ROOT/../../RPMS/*/dub*.rpm . rm -rf $RPM_BUILD_ROOT/../../RPMS/* dub-1.19.0/scripts/rpm-package/make_installer.sh000077500000000000000000000010771360435400500215700ustar00rootroot00000000000000#!/usr/bin/env bash set -e cd ../../ DUB_PATH=`pwd` #rm -f ~/rpmbuild/SOURCES/dub.tar.gz #tar -pczf ~/rpmbuild/SOURCES/dub.tar.gz source build-files.txt build.sh LICENSE* cd scripts/rpm-package/ for i in $(git describe | tr "-" "\n"); do if [ "$VER" == "" ]; then VER=${i:1} elif [ "$REL" == "" ]; then REL=0.$i else REL=$REL.$i fi done if [ "$REL" == "" ]; then REL=1 fi ARCH=$(uname -i) echo Building RPM FOR $VER-$REL-$ARCH rpmbuild -ba dub.spec --define "ver $VER" --define "rel $REL" --define="srcpath $DUB_PATH" cp ~/rpmbuild/BUILD/dub-$VER-$REL.$ARCH.rpm . dub-1.19.0/scripts/win-installer/000077500000000000000000000000001360435400500166335ustar00rootroot00000000000000dub-1.19.0/scripts/win-installer/EnvVarUpdate.nsh000066400000000000000000000251571360435400500217230ustar00rootroot00000000000000/** * EnvVarUpdate.nsh * : Environmental Variables: append, prepend, and remove entries * * WARNING: If you use StrFunc.nsh header then include it before this file * with all required definitions. This is to avoid conflicts * * Usage: * ${EnvVarUpdate} "ResultVar" "EnvVarName" "Action" "RegLoc" "PathString" * * Credits: * Version 1.0 * * Cal Turney (turnec2) * * Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this * function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, * WriteEnvStr, and un.DeleteEnvStr * * Diego Pedroso (deguix) for StrTok * * Kevin English (kenglish_hi) for StrContains * * Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry * (dandaman32) for StrReplace * * Version 1.1 (compatibility with StrFunc.nsh) * * techtonik * * http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries * */ !ifndef ENVVARUPDATE_FUNCTION !define ENVVARUPDATE_FUNCTION !verbose push !verbose 3 !include "LogicLib.nsh" !include "WinMessages.NSH" !include "StrFunc.nsh" ; ---- Fix for conflict if StrFunc.nsh is already includes in main file ----------------------- !macro _IncludeStrFunction StrFuncName !ifndef ${StrFuncName}_INCLUDED ${${StrFuncName}} !endif !ifndef Un${StrFuncName}_INCLUDED ${Un${StrFuncName}} !endif !define un.${StrFuncName} "${Un${StrFuncName}}" !macroend !insertmacro _IncludeStrFunction StrTok !insertmacro _IncludeStrFunction StrStr !insertmacro _IncludeStrFunction StrRep ; ---------------------------------- Macro Definitions ---------------------------------------- !macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString Push "${EnvVarName}" Push "${Action}" Push "${RegLoc}" Push "${PathString}" Call EnvVarUpdate Pop "${ResultVar}" !macroend !define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"' !macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString Push "${EnvVarName}" Push "${Action}" Push "${RegLoc}" Push "${PathString}" Call un.EnvVarUpdate Pop "${ResultVar}" !macroend !define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"' ; ---------------------------------- Macro Definitions end------------------------------------- ;----------------------------------- EnvVarUpdate start---------------------------------------- !define hklm_all_users 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' !define hkcu_current_user 'HKCU "Environment"' !macro EnvVarUpdate UN Function ${UN}EnvVarUpdate Push $0 Exch 4 Exch $1 Exch 3 Exch $2 Exch 2 Exch $3 Exch Exch $4 Push $5 Push $6 Push $7 Push $8 Push $9 Push $R0 /* After this point: ------------------------- $0 = ResultVar (returned) $1 = EnvVarName (input) $2 = Action (input) $3 = RegLoc (input) $4 = PathString (input) $5 = Orig EnvVar (read from registry) $6 = Len of $0 (temp) $7 = tempstr1 (temp) $8 = Entry counter (temp) $9 = tempstr2 (temp) $R0 = tempChar (temp) */ ; Step 1: Read contents of EnvVarName from RegLoc ; ; Check for empty EnvVarName ${If} $1 == "" SetErrors DetailPrint "ERROR: EnvVarName is blank" Goto EnvVarUpdate_Restore_Vars ${EndIf} ; Check for valid Action ${If} $2 != "A" ${AndIf} $2 != "P" ${AndIf} $2 != "R" SetErrors DetailPrint "ERROR: Invalid Action - must be A, P, or R" Goto EnvVarUpdate_Restore_Vars ${EndIf} ${If} $3 == HKLM ReadRegStr $5 ${hklm_all_users} $1 ; Get EnvVarName from all users into $5 ${ElseIf} $3 == HKCU ReadRegStr $5 ${hkcu_current_user} $1 ; Read EnvVarName from current user into $5 ${Else} SetErrors DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"' Goto EnvVarUpdate_Restore_Vars ${EndIf} ; Check for empty PathString ${If} $4 == "" SetErrors DetailPrint "ERROR: PathString is blank" Goto EnvVarUpdate_Restore_Vars ${EndIf} ;;khc - here check if length is going to be greater than max string length ;; and abort if so - also abort if original path empty - may mean ;; it was too long as well- write message to say set it by hand Push $6 Push $7 Push $8 StrLen $7 $4 StrLen $6 $5 IntOp $8 $6 + $7 ${If} $5 == "" ${OrIf} $8 >= ${NSIS_MAX_STRLEN} SetErrors DetailPrint "Current $1 length ($6) too long to modify in NSIS; set manually if needed" Pop $8 Pop $7 Pop $6 Goto EnvVarUpdate_Restore_Vars ${EndIf} Pop $8 Pop $7 Pop $6 ;;khc ; Make sure we've got some work to do ${If} $5 == "" ${AndIf} $2 == "R" SetErrors DetailPrint "$1 is empty - Nothing to remove" Goto EnvVarUpdate_Restore_Vars ${EndIf} ; Step 2: Scrub EnvVar ; StrCpy $0 $5 ; Copy the contents to $0 ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or ; after the last one are not removed here but instead in Step 3) ${If} $0 != "" ; If EnvVar is not empty ... ${Do} ${${UN}StrStr} $7 $0 " ;" ${If} $7 == "" ${ExitDo} ${EndIf} ${${UN}StrRep} $0 $0 " ;" ";" ; Remove ';' ${Loop} ${Do} ${${UN}StrStr} $7 $0 "; " ${If} $7 == "" ${ExitDo} ${EndIf} ${${UN}StrRep} $0 $0 "; " ";" ; Remove ';' ${Loop} ${Do} ${${UN}StrStr} $7 $0 ";;" ${If} $7 == "" ${ExitDo} ${EndIf} ${${UN}StrRep} $0 $0 ";;" ";" ${Loop} ; Remove a leading or trailing semicolon from EnvVar StrCpy $7 $0 1 0 ${If} $7 == ";" StrCpy $0 $0 "" 1 ; Change ';' to '' ${EndIf} StrLen $6 $0 IntOp $6 $6 - 1 StrCpy $7 $0 1 $6 ${If} $7 == ";" StrCpy $0 $0 $6 ; Change ';' to '' ${EndIf} ; DetailPrint "Scrubbed $1: [$0]" ; Uncomment to debug ${EndIf} /* Step 3. Remove all instances of the target path/string (even if "A" or "P") $6 = bool flag (1 = found and removed PathString) $7 = a string (e.g. path) delimited by semicolon(s) $8 = entry counter starting at 0 $9 = copy of $0 $R0 = tempChar */ ${If} $5 != "" ; If EnvVar is not empty ... StrCpy $9 $0 StrCpy $0 "" StrCpy $8 0 StrCpy $6 0 ${Do} ${${UN}StrTok} $7 $9 ";" $8 "0" ; $7 = next entry, $8 = entry counter ${If} $7 == "" ; If we've run out of entries, ${ExitDo} ; were done ${EndIf} ; ; Remove leading and trailing spaces from this entry (critical step for Action=Remove) ${Do} StrCpy $R0 $7 1 ${If} $R0 != " " ${ExitDo} ${EndIf} StrCpy $7 $7 "" 1 ; Remove leading space ${Loop} ${Do} StrCpy $R0 $7 1 -1 ${If} $R0 != " " ${ExitDo} ${EndIf} StrCpy $7 $7 -1 ; Remove trailing space ${Loop} ${If} $7 == $4 ; If string matches, remove it by not appending it StrCpy $6 1 ; Set 'found' flag ${ElseIf} $7 != $4 ; If string does NOT match ${AndIf} $0 == "" ; and the 1st string being added to $0, StrCpy $0 $7 ; copy it to $0 without a prepended semicolon ${ElseIf} $7 != $4 ; If string does NOT match ${AndIf} $0 != "" ; and this is NOT the 1st string to be added to $0, StrCpy $0 $0;$7 ; append path to $0 with a prepended semicolon ${EndIf} ; IntOp $8 $8 + 1 ; Bump counter ${Loop} ; Check for duplicates until we run out of paths ${EndIf} ; Step 4: Perform the requested Action ; ${If} $2 != "R" ; If Append or Prepend ${If} $6 == 1 ; And if we found the target DetailPrint "Target is already present in $1. It will be removed and" ${EndIf} ${If} $0 == "" ; If EnvVar is (now) empty StrCpy $0 $4 ; just copy PathString to EnvVar ${If} $6 == 0 ; If found flag is either 0 ${OrIf} $6 == "" ; or blank (if EnvVarName is empty) DetailPrint "$1 was empty and has been updated with the target" ${EndIf} ${ElseIf} $2 == "A" ; If Append (and EnvVar is not empty), StrCpy $0 $0;$4 ; append PathString ${If} $6 == 1 DetailPrint "appended to $1" ${Else} DetailPrint "Target was appended to $1" ${EndIf} ${Else} ; If Prepend (and EnvVar is not empty), StrCpy $0 $4;$0 ; prepend PathString ${If} $6 == 1 DetailPrint "prepended to $1" ${Else} DetailPrint "Target was prepended to $1" ${EndIf} ${EndIf} ${Else} ; If Action = Remove ${If} $6 == 1 ; and we found the target DetailPrint "Target was found and removed from $1" ${Else} DetailPrint "Target was NOT found in $1 (nothing to remove)" ${EndIf} ${If} $0 == "" DetailPrint "$1 is now empty" ${EndIf} ${EndIf} ; Step 5: Update the registry at RegLoc with the updated EnvVar and announce the change ; ClearErrors ${If} $3 == HKLM WriteRegExpandStr ${hklm_all_users} $1 $0 ; Write it in all users section ${ElseIf} $3 == HKCU WriteRegExpandStr ${hkcu_current_user} $1 $0 ; Write it to current user section ${EndIf} IfErrors 0 +4 MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3" DetailPrint "Could not write updated $1 to $3" Goto EnvVarUpdate_Restore_Vars ; "Export" our change SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=1 EnvVarUpdate_Restore_Vars: ; ; Restore the user's variables and return ResultVar Pop $R0 Pop $9 Pop $8 Pop $7 Pop $6 Pop $5 Pop $4 Pop $3 Pop $2 Pop $1 Push $0 ; Push my $0 (ResultVar) Exch Pop $0 ; Restore his $0 FunctionEnd !macroend ; EnvVarUpdate UN !insertmacro EnvVarUpdate "" !insertmacro EnvVarUpdate "un." ;----------------------------------- EnvVarUpdate end---------------------------------------- !verbose pop !endif dub-1.19.0/scripts/win-installer/banner.bmp000066400000000000000000004556561360435400500206250ustar00rootroot00000000000000BM[6(:x[}~uh|~uh|}tg|}tg{|sg{|sg{|sg{|sgz|sg~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~z|sg~~}}}}|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||}}}}~~y{re~~}}}||{{zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz{{||}}}~~y{re~}}}||{zzyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyzz{||}}}~y{re~~}}||{zyyxxxwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxyyz{||}}~~yzqe~~}||{zyyxxwvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvwxxyyz{||}~~yyqe~~}||{{zyywwvuuttsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssttuuvwwyyz{{||}~~wyqd~~}|~{}|y{zw{zw{zw{zw{yw{yvzyvzyvzyvzyvzyvzxvzxvywvywvywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuywuxvuxvuxvuxvuxvuxvuxvuxvuxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtxvtwvtwvtwvtwvtwvtwvtwvtwvtwvtwvtwvtwvtwvtwvtwvtwvtwutwutwutwutwutwutwutwutwuswuswuswuswuswuswuswuswusvuswuswuswuswuswutwutwvtwvtwvtxvtxvtxwtxwtywt{zw}}~~wyqd~}||[YWxxxiiiggggggggggggggggggggggggggggggggggggggggggfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddccccccccccccccccccccccccccccccccccccccccccffftttni`|}~wypd~}}|{WVSPPPxxxiiigggggggggggggggggggggggggggggggggggggggfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcccccccccccccccccccccccccccccccccccccccfffttt>>>lf^|}}~~wypd~~}|{zWUSKKKQQQ{{{iiiggggggggggggggggggggggggggggggggggggfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddccccccccccccccccccccccccccccccccccccgggqqq>>>:::kf]{|}~~~wypd~}|{zzyWUSKKKKKKQQQ{{{iiigggggggggggggggggggggggggggggggggfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddccccccccccccccccccccccccccccccccchhhsss===::::::ke]zz{|}~}wwoc~}|{{zyxWUSKKKKKKKKKQQQ{{{iiiggggggggggggggggggggggggggggggfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcccccccccccccccccccccccccccccchhhsss===;;;::::::je\yz{{|}~}vwoc}}|{zyxwWURKKKKKKKKKKKKQQQzzziiigggggggggggggggggggggggggggfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddccccccccccccccccccccccccccchhhsss===;;;;;;::::::id\xyz{|}}}vwoc~}|{{zxxvVURKKKKKKKKKKKKKKKPPPzzziiiggggggggggggggggggggggggfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddccccccccccccccccccccccccjjjppp<<<;;;;;;;;;::::::hc[xxz{{|}~}vvoc~}|{zyxwvVURKKKKKKKKKKKKKKKJJJPPPzzziiigggggggggggggggggggggfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcccccccccccccccccccccjjjrrr<<<;;;;;;;;;;;;::::::hc[wxyz{|}~|vvoc~~}{zzywvutVTRKKKKKKKKKKKKKKKJJJJJJPPP{{{iiiggggggggggggggggggfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddccccccccccccccccccjjjqqq<<<;;;;;;;;;;;;;;;::::::gbZuvwyzz{}~~{uvnb~}|{zyxwvtsVTRKKKKKKKKKKKKKKKJJJJJJJJJPPPwwwuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssrrrrrrrrrrrrrrrrrrmmm<<<;;;;;;;;;;;;;;;;;;::::::gbZtvwxyz{|}~{uvnb~}|{zyxvutsqUTQKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::faXstuvxyz{|}~~ztvna~~}|{zxwvutrqUTQKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::eaXrtuvwxz{|}~~~ztvna~~}|{zxwvusqpUTQKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::e`Xqsuvwxz{|}~~~ztvna~~}|{zxwutsq~pUSQKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::d`Xqstuwxz{|}~~~ztuma~~}{zyxvutrq}oUSQKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::d_Wqrtuvxyz{}~~~ztuma~}}|zyxwvtsq~p|nUSQKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::c^W~pqstvwxyz|}}}zsum`~}||zyxwvtrq~o|nUSQKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::c^W~oqrtvwxyz||}}zsum`~}||zyxwvtrq~o|nTSQKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::c^W~oqrtvwxyz||}}zstm`~}|{zyxwvtrq~o|nTSQKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::c^W~oqrtvwxyz{|}}zstm`}|{zyxwvusrp}n{mTSQKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::b^V}nprsuvwxyz{||yrsl_}|{zyxwvusrp}n{mTSQKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHFNT?m?=99799<>?~BUaFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDCFH>h><:9788;>=>YiBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@???????@A;\p<<:88789;;:Zn>@A=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::b^V}nprsuvwxyz{||yrsl_}|{zyxwvusr~p|nzmTSQKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHGKN?z<73*((((((((.6:@DV`FFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDEE@u=73*((((((((-58>@\mAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@=dz=84,((((((((-57<:bz===============<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::b]V|n~prsuvwxyz{||yrsk_}|{zyxwvusr~p|nzmTSQKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIHLO@90((((((((((((((()5>EapFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDFFA:/((((((((((((((((3;@lAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@w:1((((((((((((((()3:BS\AAAAAAAAAAAA@@@@@@@@@@@@A^l<-((((((((((((((((((((0<<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::b]V|n~oqrtuvwxyz{{xqsk^|{zyxwvutrq}o{nylTSPKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIGW_=*((((((((((((((((((((((((((2DEEEEEEEEEEQW@)((((((((((((((((((((((((((.BABBAAA@@@@CDA+((((((((((((((((((((((((((->=@C<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::b]V{n}oqrtuvwxyz{{xqrj^|{zyxwvutrq}o{nylTSPKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIG[g<(((((((((((((((((((((((((((((.DEEEFW^=(((((((((((((((((((((((((((((*AABBAGI?)((((((((((((((((((((((((((((*==DG<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::b]V{n}oqrtuvwxyz{{xqrj^{zyxwvutsqp}n{mykTSPKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIHT[<(((((((((((((((((((((((((((((((.F=(((((((((((((((((((((((((((((((*B@)(((((((((((((((((((((((((((((((>=?A<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::b]U{m}npqstuvwxyzzwprj^{zyxwvutsqp}n{mykTSPKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIKK?(((((((((((((((((((((((((((((((((+(((((((((((((((((((((((((((((((((*)(((((((((((((((((((((((((((((((()@<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::b]U{m}npqstuvwxyzzwprj^zyxwvutsrp~o|mzlyjTRPKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJB*((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((,A|<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::a]Uzl|m~oprstuvwxyyv~oqj]zyxwvutsrp~o|mzlyjTRPKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJGn1((((((((((((((6?BCB@;+((((((((((((((((((((((((((2>@AB@<-((((((((((((((((((((((((((.<>??>=.((((((((((((((4?T]<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::a]Uzl|m~oprstuvwxyyv~oqj]zyxwvutsr~p}o{mylxjTRPKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJKK>((((((((((((,AI{IY`GGGGGGGGGGGGGGGHNQJsD1((((((((((((((((((((()=F~F\eCCCCCCCCCCCCCCCBEFFjyC5((((((((((((((((((((((7CDcq?AB???>>>>>>>>>>@AC`lB7(((((((((((((?<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::a\Uyl{m}o~prstuvwxyyv}opi]zyxwvutsr~p}o{mylxjTRPKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJG,(((((((((((:IwHIIHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFHftA(((((((((((((((((((6E~CGICCCCCCCCCCCCCCCCCCCCCBBBBBBBBBE\eB+((((((((((((((((((-CBRY????????????>>>>>>>>>>>>>>>>>>APWC-(((((((((((.Adt<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::a\Uyl{m}o~prstuvwxyyv}opi]zyxwvutsq~p}n{mykxjTRPKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJ>(((((((((()AHX_HHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFGLOE+((((((((((((((((=D^iDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBDEE/((((((((((((((((0D|?@A???????????????>>>>>>>>>>>>>>>>>>>>>>?@Dz0(((((((((((?<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::a\Uyk{m}n~pqstuvwxyyv}npi]zyxwvutsq~p|nzmykwjTRPKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJHl~/((((((((((@HLNHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFGGE(((((((((((((((>>>>>>>>>>>>>>>>>>>>>>>===Dy,((((((((((2@Wa;;;;;;;;;;;;;;;;;;;;;;;;::::::`\Uykzm|n~pqstuvwxyyv}nph]zyxwvutsq~p|nzmykwjTRPKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJB((((((((((:HU\HHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFGLOA(((((((((((((6C]jDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBEFB((((((((((((((D?@A?????????????????????>>>>>>>>>>>>>>>>>>>>>>>>====>?B~(((((((((((B{;;;;;;;;;;;;;;;;;;;;;;;;::::::`\Uykzm|n~pqstuvwxyyv}nph]yxwvutsrp~o|mzlyj~wiSRPKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJ<(((((((((,E~HHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFHhw0(((((((((((,@DDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBDZc4((((((((((((9CV^????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>======@S[7((((((((((>;;;;;;;;;;;;;;;;;;;;;;;;::::::`\Tyjzl|m~oprstuvwxxu}noh\zyxwvutsq~p|nzmyk~wjSRPKKKKKKKKKKKKKKKJJJJJJJJJJJJJY`2(((((((((=HHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFC(((((((((((:DGHDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAD((((((((((()F~@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=========Dw)(((((((((5>KQ;;;;;;;;;;;;;;;;;;;;;::::::`\Uykzm|n~pqstuvwxyyv}noh]zyxwvuts~q}p{nymxk~vjSRPKKKKKKKKKKKKKKKJJJJJJJJJJJJG}*(((((((()CHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFHt*((((((((()?DDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAFgu-((((((((((0Ees@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=========Cfu0(((((((((+Bet;;;;;;;;;;;;;;;;;;;;;::::::`[Uxkym{n}p~qstuvwxyyv|nog]yxwvutsr~p|ozmylwj~uiSRPKKKKKKKKKKKKKKKJJJJJJJJJJJJE(((((((((4HYbHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFGOS9(((((((((3>dzDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAABFH=((((((((((?AEG@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=========>EH=((((((((((Bo;;;;;;;;;;;;;;;;;;;;;::::::`[Twjylzm|o~prstuvwxxu{nng\yxwvutsr~p|ozmyl~wj}uiSRPKKKKKKKKKKKKKKKJJJJJJJJJJJJC(((((((((:IIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFE(((((((((6BJPDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAK((((((((((M@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>============Az((((((((((Ax;;;;;;;;;;;;;;;;;;;;;::::::_[T~wjylzm|o~prstuvwxxu{nmg\yxwvutsr~p|ozmyl~wj}uiSRPKKKKKKKKKKKKKKKJJJJJJJJJJJJB(((((((((>>>>>>>>>>>>>>>>>>>>>>>============Cv((((((((((B~;;;;;;;;;;;;;;;;;;;;;::::::_[T~wjylzm|o~prstuvwxxu{nmg\xwvutsr~q}o{nylxk~vi}thSRPKKKKKKKKKKKKKKKJJJJJJJJJJJJ@(((((((((>>>>>>>>>>>>>>>>>>>>>>>============Dr((((((((((@{;;;;;;;;;;;;;;;;;;;;;::::::_ZS~vixkyl{n}o~qrstuvwwtzmmf[xwvutsr~q}o{nylxk~vi}thSRPKKKKKKKKKKKKKKKJJJJJJJJJJJJC(((((((((;IIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFM(((((((((:DDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAZ((((((((((V@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>============Cy((((((((((A{;;;;;;;;;;;;;;;;;;;;;::::::_ZS~vixkyl{n}o~qrstuvwwtzmmf[wvutsr~q}p|nzmxkwj~ui|tgSROKKKKKKKKKKKKKKKJJJJJJJJJJJJD(((((((((7IIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFG(((((((((:IIIDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAABBBZ((((((((((Q@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>============A((((((((((Bu;;;;;;;;;;;;;;;;;;;;;::::::^ZS~uiwjxkzm|n}p~qrstuvvsylme[wvutsr~q}p|nzmxkwj}ui{tgSROKKKKKKKKKKKKKKKJJJJJJJJJJJJF(((((((((/FoHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFGUZ8(((((((((9^^^DDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAOOOY((((((((((DBQX@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=========?IN:((((((((()Ck};;;;;;;;;;;;;;;;;;;;;::::::^ZS}uiwjxkzm|n}p~qrstuvvsylle[wvutsr~q}p|nzmxkwj}ui{tgSROKKKKKKKKKKKKKKKJJJJJJJJJJJJIu*(((((((((AHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFG((((((((((9qqqDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAbbbY((((((((((.Fo@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=========Dj{-(((((((((/@]i;;;;;;;;;;;;;;;;;;;;;::::::^ZS}uiwjxkzm|n}p~qrstuvvsylle[vutsrq~p|o{mylxkvi}th{sfSROKKKKKKKKKKKKKKKJJJJJJJJJJJJKSW5(((((((((8GSYHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFGG?((((((((((9sssOOODDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBCCCkkkZ(((((((((((C@AA????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=========B((((((((((:<@A;;;;;;;;;;;;;;;;;;;;;::::::^ZR}thvixkyl{m|o~pqrstuurxkldZvutsrq~p|o{mylxk~vi|thzsfSROKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJ?((((((((()AHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFF{+((((((((((9iiiqqqDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBB]]]iiiZ(((((((((((0Ek{????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>======Cds1((((((((((@;;;;;;;;;;;;;;;;;;;;;;;;::::::]ZR|th~vixkyl{m|o~pqrstuurxkkdZvutsrq~p|o{mylxk~vi|thzsfSROKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJF((((((((((2DqHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFYb9(((((((((((9hhhpppcccDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBLLLnnnhhhZ((((((((((((>@IM?????????????????????>>>>>>>>>>>>>>>>>>>>>>>>===>EH>((((((((((*Cp;;;;;;;;;;;;;;;;;;;;;;;;::::::]ZR|th~vixkyl{m|o~pqrstuurxkkdZutsrq~p}o|nzmxkwj}uh{tgyreSQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJ\d3((((((((((7FaqHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFGNR>((((((((((((9hhhhhhrrrZZZDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBFFFppphhhhhhZ(((((((((((((B?AB??????????????????>>>>>>>>>>>>>>>>>>>>>>>>=>?A(((((((((((9>FJ;;;;;;;;;;;;;;;;;;;;;;;;::::::]YR{tg}uhwjxkzm|n}o~pqrstt~qwjjdYutsr~q}p|o{nymwkvj}th{sgyqeSQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJB(((((((((((7DsHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFEXb=)((((((((((((9hhhhhhhhhrrrcccDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBJJJpppiiihhhhhhZ(((((((((((((*@@FH???????????????>>>>>>>>>>>>>>>>>>>>>>AC@*(((((((((((B<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::]XR{sg}thvjwkym{n|o}p~qrstt}qwjjcYtsrq~p}o|n{mylwj~vi|tgzsfyqeRQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJIk{/(((((((((((2AFRXHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFC8((((((((((((((9hhhhhhhhhhhhoooqqqOOOCCCCCCCCCCCCCCCCCCCCCBBBBBBCCC___rrriiihhhhhhhhhZ(((((((((((((();@k????????????>>>>>>>>>>>>>>>>>>?g|=)(((((((((((5?OV<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::]XRzsf|tg~viwjyl{m|n}o~pqrss}p~wijcXtsrq~p}o|n{mylwj~vi|tgzsfyqeRQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJC(((((((((((()8@CrGHHGGGGGGGGGGGGD]kB<,(((((((((((((((9hhhhhhhhhhhhhhhiiisssooo^^^FFFCCCCCCCCCCCCKKKeeeqqqnnnhhhhhhhhhhhhhhhZ((((((((((((((((0HN???>>>>>>>>>=FK?=0(((((((((((()C<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::]XRzsf|tg~viwjyl{m|n}o~pqrss}p~wijcXtsr~q}p|o{nzmxl~wj}ui{sgyrfxpeRQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJZa8((((((((((((((07:::83)(((((((((((((((((9hhhhhhhhhhhhhhhhhhhhhhhhnnnttttttqqqssssssssskkkhhhhhhhhhhhhhhhhhhhhhZ((((((((((((((((((+579986+((((((((((((((==CE<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::\XRyrf{sg}ui~wjxlzm{n|o}p~qrss|p}viibXsr~q}p|o{nzmylwk~vi}th{sgyqexodRQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJH|.((((((((((((((((((((((((((((((((((((((9hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhZ(((((((((((((((((((((((((((((((((((((((3@[g<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::\WQyqe{sg}th~viwkylzm{n|o}p~qr~r{o}uhiaXsr~q}p|o{nzmylwk~vi}th{sgyqexodRQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIE*(((((((((((((((((((((((((((((((((((((9hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhZ((((((((((((((((((((((((((((((((((((((/Au<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::\WQyqe{sg}th~viwkylzm{n|o}p~qr~r{o}uhiaXr~q}p|o{nzmylxk~vj}ui{sgyrfxpdvocRQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIJJC)((((((((((((((((((((((((((((((((((((9hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhZ(((((((((((((((((((((((((((((((((((((,B<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::[WQxpdyrf{sg}ui~vjxkylzm{n|o}p~q~qzn|tggaWr~q}p|o{nzmylxk~vj}ui{sgyrfxpdvocRQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIILMC*(((((((((((((((((((((((((((((((((((9hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhZ((((((((((((((((((((((((((((((((((((.A<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::[WQxpdyrf{sg}ui~vjxkylzm{n|o}p~q~qzn|tggaWq~p}o|n{mzlykxj~vi}uh{sfyrexpcvobRQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIJJE.((((((((((((((((((((((((((((((((((9hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhZ(((((((((((((((((((((((((((((((((((3Av<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::[WPxpcyre{sf}uh~vixjykzl{m|n}o~p~pzm|tfgaV~q}p|o{nzmylxkwj~vi|thzrfyqewocunbRQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIHz8((((((((((((((((((((((()(((((((((9iiihhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh[(((((((((()(((((((((((((((((((((()<@^l<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::[WPwocyqezrf|th~viwjxkylzm{n|o}p}pzm{sfg`V}p|o{nzmylxkwjvj~uh|sgzreypdwncumaRQNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIY_C1(((((((((((((((((((,?C(((((((((7lllnnnhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiinnnX((((((((((D;+(((((((((((((((((((5A>AC===<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::[VPwncypdzre|sg~uhvjwjxkylzm{n|o|oyl{reg_U}p|o{nzmylxkwjvj~uh|sgzreypdwncumaRQNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHgvB5(((((((((((((((0>FxFFFC(((((((((6DDDTTTllloooiiihhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhkkkooogggIIIDx((((((((((Dq@AA@;,((((((((((((((*8@?LR=========<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::[VPwncypdzre|sg~uhvjwjxkylzm{n|o|oyl{reg_U|o{nzmylxkwj~vj}ui|tgzrfxqewocunbtl`RPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHY_F?8+(((((((*5=CGbpFFFFFFFFFC(((((((((6DDDDDDDDDMMMfffnnnooommmiiihhhhhhhhhhhhhhhhhhjjjnnnppplll^^^FFFAAAAAADx((((((((((Dq@@@@@@?@ABn>:1)(((((((.9>Aw>DF===============<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::ZVOunbwocxqezrf|tg}ui~vjwjxkylzm{n{nxkyqee^U|o{nzmylxkwj~vj}ui|tgzrfxqewocunbtl`RPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHNQHqGCBABDEGuGQUFFFFFFFFFFFFFFFFFFC(((((((((6DDDDDDDDDDDDDDDDDDHHHXXXeeeiiikkkkkkllliiiiiiaaaTTTDDDBBBBBBBBBAAAAAADx((((((((((Dq@@@@@@????????????BT]C{A?>>>@B{A^l>@A>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::ZVOunbwocxqezrf|tg}ui~vjwjxkylzm{n{nxkyqee^U{oznymxlwkvj~uj}ti|sgzqfxpewncumbtk`RPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFC(((((((((6DDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAADx((((((((((Dq@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::ZUOumbwncxpezqf|sg}ti~ujvjwkxlymznznwkypee^U{nzmylxkwjvj~ui|th{sfyqexpdvnbtmask`RPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFC(((((((((6DDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAADx((((((((((Dq@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::ZUOtmavnbxpdyqe{sf|th~uivjwjxkylzmzmwjxpdd^Tzmylxkxkvj~ui}th|sgzrexpdwocumatl`rj_QPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFC(((((((((6DDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAADx((((((((((Dq@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::YUNtl`umawocxpdzre|sg}th~uivjxkxkylyl~viwocd]Szmylxkxkvj~ui}th|sgzrexpdwocumatl`rj_QPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFC(((((((((6DDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAADx((((((((((Dq@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::YUNtl`umawocxpdzre|sg}th~uivjxkxkylyl~viwocd]Szmylylxkvj~ui}th|sgzrexpdwocvnbtlarj_QPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFC(((((((((8DDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAD{((((((((((Es@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::YUNtlavnbwocxpdzre|sg}th~uivjxkylylyl~viwocd]Sylxkwkvj}ui|th{sgzrfxpewocvnbtlark`pi^QPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFE(((((((((;DDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAFy((((((((()Gs@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::XTNrk`tlavnbwocxpezrf{sg|th}uivjwkxkxk|uhvnbb\Rykxjwjvi}uh|tg{sfzreyqdwocvnbtmark_qj^QPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFHhw.(((((((*>DDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAE_k2((((((((5D\g@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::XUNrk_tmavnbwocyqdzre{sf|tg}uhviwjxjxj|ugvnab\Rxkwjvj~ui}th{sgzrfyqexpdwocumbtlarj_pi^QPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFC)((((((:BMTDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAC*((((((+E@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::XTNrj_tlaumbwocxpdyqezrf{sg}th~uivjwj~wj{tgumaa[Rxj~wi~vi}uh|tg{sfzrexqewpdvocunbsl`rk_qj^QPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFFJL@/(((*;AdwDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAADEA2((((4B@AA@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::XUNrk_sl`unbvocwpdxqezre{sf|tg}uh~vi~wi~wiztftmaa[Qxj~wi~vi}uh|uh{tgzsfyrexqdvocunbtmasl`qj^QPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEECo?;;;>@Vb@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::XUNsl`tmaunbvocxqdyrezsf{tg|uh}uh~vi~wi~wiztftmaa[Qwkvj~vi}uh|th{sgzrfzqexpdwocvnbumbsk`rj_RPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::YUNsk`umbvnbwocxpdzqezrf{sg|th}uh~vivj~vjzsftlaa[Q~vi}uh|ug{tg{sfzreyqdxpdwocvnbumatm`sl_qj^QPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::XUNsl_tm`umavnbwocxpdyqdzre{sf{tg|ug}uh}uhyrdrk_`ZO~vi}vh|ug|tg{sfzsfyrexqdwpcvobunatmasl`rk^RPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::YUNsl`tmaunavobwpcxqdyrezsf{sf|tg|ug}vh}uhyrdrl_`ZO~ui}uh|tg|sg{rfzrfyqeypdxodwocvnbumatl`sk_RPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::ZUNtl`umavnbwocxodypdyqezrf{rf|sg|tg}uh}thyqdrk_`YO}uh|tg|sg{sfzrfzqeypdxpdwocvnbumaumatl`rj_RPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::YUNtl`umaumavnbwocxpdypdzqezrf{sf|sg|tg|tgypdqj^_XO}uh}th|sg{sf{rfzqeyqexpdxpdwocvnbumatlask`RPNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::ZUOtlaumavnbwocxpdxpdyqezqe{rf{sf|sg}th|tgypdqj^_XO|uh|th{tg{sgzsfyrfyqexpdwpdvocvocunbtmasl`RQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::ZVOtmaunbvocvocwpdxpdyqeyrfzsf{sg{tg|th{tgxqdqj^^XO}th|tg|sg{rfzrfzqeypdxpdxpcwocvnbumaumatl`RQNKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::ZVOumaumavnbwocxpcxpdypdzqezrf{rf|sg|tg|sgxpdqi]^XO|th{tg{sgzsfzrfyrfxqexpdwpdvocvocunbtmaslaRQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::ZVPtmaunbvocvocwpdxpdxqeyrfzrfzsf{sg{tg{sgwpdpi]^XO|tg{sg{sfzrfyqeyqexpdxpdwpcvocvnbunbtmatl`RQOKKKKKKKKKKKKKKKJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAA@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>=====================<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;::::::ZVOtmaunbvnbvocwpcxpdxpdyqeyqezrf{sf{sg{sfwodoh]^XN|tg{sg{sfzrfzreyqeyqexpdwpcwocvocvnbumatmatl`sk`rk_qj^qi^pi]oh]ng\ng[mf[leZkdYkdYjcYjcXibXibXibXibXibXibXibXibXibXibXtogwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwtogibYibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXjcXjcYkdYkdYleZmf[ng[ng\oh]pi]qi^qj^rk_sk`tl`tmaumavnbvocwocwpcxpdyqeyqezrezrf{sf{sg{sfwodpi]^XN|sh|sg{rg{rfzqfzqeypeypexpdwocwncvncvmbulatlatk`sj`rj_rj_qi^ph^ph]og\nf\nf[me[ldZldZkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYvpiyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyvpikcZkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYldZldZme[nf[nf\og\ph]ph^qi^rj_rj_sj`tk`tlaulavmbvncwncwocxpdypeypezqezqf{rf{rg|sg{rgwndph]^WN{sg{sfzrfzrezreyqexpdxpdxpdwocvobvnbunbumatmasl`sk`rk_rj_qj^pi]pi]oh\oh\ng[mf[mf[leZleZleZleZleZleZleZleZleZleZwrjyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzwrjle[leZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZmf[mf[ng[oh\oh\pi]pi]qj^rj_rk_sk`sl`tmaumaunbvnbvobwocxpdxpdxpdyqezrezrezrf{sfzrfwocoh\]WMzrgzrgzrfyqfyqexpexpdwodwodvocvncunbumbtmbtlaslask`rk`rj`qj_pi^pi^oh]oh]ng\ng\mf\mf[le[le[le[le[le[le[le[le[xsk{|||||||||||||||||||||||||||||||||||||||||||||||||||||xskle\le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[le[mf[mf\ng\ng\oh]oh]pi^pi^qj_rj`rk`sk`slatlatmbumbunbvncvocwodwodxpdxpeyqeyqfzrfzrgyqfvncng\]WN{sgzrgzrfzrfyqfyqexpexpdwodwodvocvncunbumbtmbtlaslask`rk`rj`qj_qj_pi^pi^oh]oh]oh]ng]ng\ng\ng\ng\ng\ng\ng\zum}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~zumng]ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng]oh]oh]oh]pi^pi^qj_qj_rj`rk`sk`slatlatmbumbunbvncvocwodwodxpdxpeyqeyqfzrfzrfzrgzrfvncng\]WN{rfzqfzqfzqeypeypdypdxodxodwocwncwncvnbumaumaulatk`tk`sk`sj_rj_rj_qi^qi^ph]ph]ph]og]og]og]og]og]og]og]|vm~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|vmog]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]og]ph]ph]ph]qi^qi^rj_rj_sj_sk`tk`tk`ulaumaumavnbwncwncwocxodxodypdypdypezqezqfzqfzqevmbog\]VMzrezreyqeyqeyqdxpdxpcxpcwocwocvobvnbvnbunaumatmatl`sl`sk_sk_rk_rj_qj^qj^qj^pi]pi]pi]pi]oh\oh\oh\oh\|wn|wnoh]oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\oh\pi]pi]pi]pi]qj^qj^qj^rj_rk_sk_sk_sl`tl`tmaumaunavnbvnbvobwocwocxpcxpcxpdyqdyqeyqezreyqdumang\\VLzrezrezreyqeyqeyqdxpdxpcxpcwocwocvobvnbvnbunaumatmatmatl`sl`sk_sk_rk_rj_qj^qj^qj^qj^qj^qj^qj^qj^~xo~xoqj_qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^qj^rj_rk_sk_sk_sl`tl`tmatmaumaunavnbvnbvobwocwocxpcxpcxpdyqdyqeyqezrezreyqdvnbng\\VLzrfyqeyqeyqexpexpexpdwodwocwocvncvncvncunbumbumbtmatlaslaslask`rk`rj_rj_rj_qj_qj_qj_qj_qj_qj_xpxpqj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_rj_rj_rj_rk`sk`slaslatlatmaumbumbunbvncvncvncwocwocwodxpdxpexpeyqeyqeyqeyqeumbnf\[ULzreyqdyqdyqdyqdxpdxpdxpcwocwocwobwobvnbvnbunaumaumaumatm`tl`sl`sl`sk_sk_rk_rk_rj^rj^rj^rj^ypyprj_rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rj^rk_rk_sk_sk_sl`sl`tl`tm`umaumaumaunavnbvnbwobwobwocwocxpcxpdxpdyqdyqdyqdyqdyqdumanf[[ULzrezreyqdyqdyqdyqdxpdxpdxpcxpcwocwobwobvnbvnbvnbunaumaumaumatm`tm`tl`sl`sl`sl`sl`sk_sk_zqzqsk`sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sl`sl`sl`sl`tl`tm`tm`umaumaumaunavnbvnbvnbwobwobwocxpcxpcxpdxpdyqdyqdyqdyqdzreyqdumanf[[ULzqezqezqeypdypdypdypdxodxodxocxocwncwncwnbwnbvnbvnbvmbumaumaulaulaulatl`tl`tl`tl`tk`{r{rtlatk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tk`tl`tl`tl`tl`ulaulaulaumaumavmbvnbvnbwnbwnbwncwncxocxocxodxodypdypdypdypdzqezqeypdulane[\ULzqezqezqezqeypdypdypdypdxodxodxodxocxocwncwncwnbwnbvnbvnbvmbvmbumaumaumaulaulaula|s|sumbulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaumaumaumavmbvmbvnbvnbwnbwnbwncwncxocxocxodxodxodypdypdypdypdzqezqezqeypdulane[\ULypdypdypdypdypdypdxocxocxocxocwncwncwncwnbwnbvmbvmbvmavmavmaumaumaumaulaulaula|s|rtmatl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`ulaulaulaulaulaumaumaumavmavmavmavmbvmbwnbwnbwncwncwncxocxocxocxocypdypdypdypdypdxoctk`ne[[ULypdypdypdypdypdypdypdxocxocxocxocxocwncwncwncwnbwnbvmbvmbvmbvmavmavmavmavma}s}tunbumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumavmavmavmavmavmavmbvmbvmbwnbwnbwncwncwncxocxocxocxocxocypdypdypdypdypdypdxoculane[[ULyqexpdxpdxpdxpdxpdxpdxpdxpdwocwocwocwocwocvncvncvncvncvnbvnbvnbumbumbumb~t}uunbumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumbumbumbumbumbumbumbvnbvnbvnbvncvncvncvncwocwocwocwocwocxpdxpdxpdxpdxpdxpdxpdxpdxpdtlame[[ULypdypdypdxocxocxocxocxocxocxocxocwnbwnbwnbwnbwnbwnbvmbvmbvmbvmbvmbvmb}u}uvnbvmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmavmbvmbvmbvmbvmbvmbwnbwnbwnbwnbwnbwnbxocxocxocxocxocxocxocxocypdypdxoctk`meZ[TKypdypdypdypdxocxocxocxocxocxocxocxocxocwnbwnbwnbwnbwnbwnbwnbwnbwnb~u~uvncvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbvmbwnbwnbwnbwnbwnbwnbwnbwnbwnbxocxocxocxocxocxocxocxocxocypdypdypdxoctk`meZ[TKypdypdypdypdypdypdxocxocxocxocxocxocxocxocxocxocwnbwnbwnbwnbwnbv~vwocwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbxocxocxocxocxocxocxocxocxocxocypdypdypdypdypdxoctk`meZ[TKxpdxpdxpdxpdxpdxpdxpdxpdwocwocwocwocwocwocwocwocwocwocwocwocwwwpdwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocxpdxpdxpdxpdxpdxpdxpdwocsk`leZZTKxpdxpdxpdxpdxpdxpdxpdxpdxpdxpdxpdwocwocwocwocwocwocwocwocwwwpdwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocxpdxpdxpdxpdxpdxpdxpdxpdxpdxpdwocsk`leZZTKwocwocwocwocwocwocwocwocwocwocwocwocwocwocwocvnbvnbvnbvvvocvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbwocwocwocwocwocwocwocwocwocwocwocwocwocwocvnbrj_kdYYSJwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbuvwocwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbvmari^kcXYRIwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbuvwocwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbvmari^kcXYRIwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbvvwocwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbwnbvmari^kcXYRIvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvvwocvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbumaqi^jcXXRIvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvvwocvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbvnbumaqi^jcXXRIumaumaumaumaumaumaumaumaumaumaumauma~vvvnbumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumatl`ph]ibWXRIumaumaumaumaumaumaumaumaumaumauma~v~vvnbumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumaumatl`ph]ibWXRIulaulaulaulaulaulaulaulaulaula~v~vvmbulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulatk`pg]iaWXQIulaulaulaulaulaulaulaulaula~v~vvmbulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulaulatk`pg]iaWXQItl`tl`tl`tl`tl`tl`tl`tl`~u~uumbtl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`sk_og\haVWQHtl`tl`tl`tl`tl`tl`tl`~u~uumbtl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`tl`sk_og\haVWQHsk`sk`sk`sk`sk`sk`}u}utlbsk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`rj_nf\g`VVPHsk`sk`sk`sk`sk`}t}utlbsk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`rj_nf\g`VVPHsk`sk`sk`sk`}t}utlbsk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`rj_nf\g`VVPHsk_sk_sk_}t}ttlask_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_rj^nf[g`UVPGsk_sk_}t}ttlask_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_rj^nf[g`UVPGsk_}t}ttlask_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_sk_rj^nf[g`UVPG}s}tskarj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_qi^me[f_UUOG}tskarj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_rj_qi^me[f_UUOG|srj`qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^ph]ldZe^TUOF|srj`qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^ph]ldZe^TUOF|srj`qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^ph]ldZe^TUOF|rrj_qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]ph\ldYe^TUOF|rrj_qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]ph\ldYe^TUOF|rrj_qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]qi]ph\ldYe^TUOF{rqj_ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]og\kdYe]TTNF{rqj_ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]og\kdYe]TTNF{rqj`ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]ph]og\kdYe]TTNFzqpi_og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\nf[jcXd\SSMEzqpi_og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\nf[jcXd\SSMEzqpi_og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\nf[jcXd\SSMEzqpi_og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\nf[jcXd\SSMEzqpi_og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\nf[jcXd\SSMEzqpi_og\og\og\og\og\og\og\og\og\og\og\og\og\og\og\nf[jcXd\SSMEzqpi_og\og\og\og\og\og\og\og\og\og\og\og\og\og\nf[jcXd\SSMEypoh^nf[nf[nf[nf[nf[nf[nf[nf[nf[nf[nf[nf[nf[meZibWc\RRLDypoh^nf[nf[nf[nf[nf[nf[nf[nf[nf[nf[nf[nf[meZibWc\RRLD~ypoh^mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[leZhbWb\RRLD~ypoh^mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[leZhbWb\RRLD~ypoh^mf[mf[mf[mf[mf[mf[mf[mf[mf[leZhbWb\RRLD~ypoh^mf[mf[mf[mf[mf[mf[mf[mf[leZhbWb\RRLD~ypoh^mf[mf[mf[mf[mf[mf[mf[leZhbWb\RRLD~xoog]meZmeZmeZmeZmeZmeZldYhaVb[QRLC~xoog]meZmeZmeZmeZmeZldYhaVb[QRLC~xoog]meZmeZmeZmeZldYhaVb[QRLC}wong]ldZldZldZkcYg`VaZQQKC}wong^ldZldZkcYg`VaZQQKC}wong^ldZkcYg`VaZQQKC}womg^jcYf`V`ZQPKC}wolf]f`V`ZQPKC|vnhcZ`ZQPKCxrjb\TPKC~pkdRMF}|v^YTkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYnh^kdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYjcXf`U`ZPPKCkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYnh^kdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYjcXf`U`ZPPKCkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYnh^kdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYkdYjcXf`U`ZPPKCjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYmg^jcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYibXe_U_YPOJCjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYmg^jcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYibXe_U_YPOJCjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYmg^jcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYibXe_U_YPOJCjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYmg^jcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYibXe_U_YPOJCicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXlg]icXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXhbWd_T^YOOJBicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXlg]icXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXhbWd_T^YOOJBicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXlg]icXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXhbWd_T^YOOJBicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXlg]icXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXhbWd_T^YOOJBicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXlg]icXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXicXhbWd_T^YOOJBibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWlf\ibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWhaVd^S^XNOIAibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWlf\ibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWhaVd^S^XNOIAibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWlf\ibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWhaVd^S^XNOIAibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWlf\ibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWhaVd^S^XNOIAibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWlf\ibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWibWhaVd^S^XNOIAhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWke\haWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWg`Vd]S]WNNIAhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWke\haWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWg`Vd]S]WNNIAhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWke\haWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWg`Vd]S]WNNIAhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWke\haWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWg`Vd]S]WNNIAhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWke\haWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWg`Vd]S]WNNIAgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVje[gaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVf`Uc]R\WMMI@gaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVje[gaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVf`Uc]R\WMMI@gaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVje[gaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVf`Uc]R\WMMI@gaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVje[gaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVf`Uc]R\WMMI@gaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVje[gaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVf`Uc]R\WMMI@gaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVje[gaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVgaVf`Uc]R\WMMI@g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vjd[g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vf_Uc\R\VMMH@g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vjd[g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vf_Uc\R\VMMH@g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vjd[g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vf_Uc\R\VMMH@g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vjd[g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vf_Uc\R\VMMH@g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vjd[g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vf_Uc\R\VMMH@g_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_UjcZg_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Uf^Tc[Q\ULMG@g_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_UjcZg_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Uf^Tc[Q\ULMG@g_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_UjcZg_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Uf^Tc[Q\ULMG@g_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_UjcZg_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Uf^Tc[Q\ULMG@g_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_UjcZg_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Ug_Uf^Tc[Q\ULMG@g_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vjc[g_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vf^Uc[R\UMMG@g_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vjc[g_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vf^Uc[R\UMMG@g_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vjc[g_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vg_Vf^Uc[R\UMMG@g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vjd[g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vf_Uc\R\VMMH@g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vjd[g`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vg`Vf_Uc\R\VMMH@haWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWke\haWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWhaWg`Vd]S]WNNIAiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWle\iaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWiaWh`Vd]S^WNOIAibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXlf]ibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXibXhaWd^T^XOOIBjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYmg^jcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYjcYibXe_U_YPOJCkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYng^kcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYkcYjbXf_U`YPPJCkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZnh_kdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZkdZjcYf`V`ZQPKCleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZoi_leZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZleZkdYgaVa[QQLCmf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[pi`mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[leZhbWb\RRLDmf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[pi`mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[leZhbWb\RRLDmf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[pi`mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[mf[leZhbWb\RRLDng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\pjang\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\ng\mf[icXc\SRMEoh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]qkaoh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]ng\jdYd]TSNFoh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]qkaoh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]oh]ng\jdYd]TSNFpi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^rlbpi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^pi^oh]kdZe^TTOFqi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^slbqi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^qi^ph]ldZe^TUOFqj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_smcqj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_qj_pi^le[e_UUOGrk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_tncrk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_qj^mf[f`UUPGrk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_tncrk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_rk_qj^mf[f`UUPGsk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`undsk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`sk`rj_nf\g`VVPHsl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`uodsl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`sl`rk_ng\gaVVQHtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbvpftmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbtmbslaoh^hbXWRIumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbwpfumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbumbtlaph^ibXXRIvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncwpgvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncvncumbqi_jcYXRJwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncxpgwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncwncvmbri_kcYYRJwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodxqhwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodwodvncrj`kdZYSKxpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpeyrixpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpewodskale[ZTLxpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpeyrixpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpexpewodskale[ZTLypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypezriypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypeypexodtkame[[TLyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfzsiyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfyqfxpetlbme\[ULzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrf{tizrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfzrfyqeumbnf\[UL{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg|uj{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sg{sgzrfvncng\\VM{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg|vj{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tg{tgzsfvocnh\\WM|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th}vk|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th{sgwodoh]]WN}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh~wk}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh}uh|tgxpdpi]^XN}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui~wl}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui}ui|thxpdpi^^XO}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj~wm}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj}uj|tixpepi_^XO~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~wm~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj~vj}uiyqeqj_^XOwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkxnwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwk~vjzrfrk`_YPwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkxnwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwkwk~vjzrfrk`_YPxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlyoxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxlxl~wkzsgsla`ZQymymymymymymymymymymymymymymymymymymymzpymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymxl|thumba[Rymymymymymymymymymymymymymymymymymymymzpymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymymxl|thumba[Rznznznznznznznznznznznznznznznznznznzn{pznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznym}uivncb[Rznznznznznznznznznznznznznznznznznznzn{pznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznznym~uiwncc[R{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n|p{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{n{nzm~viwncc\R|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p}r|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p|p{o~wkwoec]T}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p~r}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p}p|oxkwped^T}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q~s}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q}q|pxlxped^U~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~s~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q~q}pylxqed^U~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~t~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r~r}qymyqfe^Usssssssssssssssssssussssssssssssssssssssssssssssssssssssssssssssssssssss~rznzrgf_Vsssssssssssssssssssussssssssssssssssssssssssssssssssssssssssssssssssssss~rzn{sgg`Vtttttttttttttttttttvtttttttttttttttttttttttttttttttttttttttttttttttttttt~szo|shg`Wtttttttttttttttttttvtttttttttttttttttttttttttttttttttttttttttttttttttttt~szo|shg`Wvvvvvvvvvvvvvvvvvvvwvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvu|q}ujhaXvvvvvvvvvvvvvvvvvvvwvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvu}q~vjibXvvvvvvvvvvvvvvvvvvvwvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvu}q~vjibXwwwwwwwwwwwwwwwwwwwxwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwv~rwkjcYxxxxxxxxxxxxxxxxxxxyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxw~swljcZyyyyyyyyyyyyyyyyyyyzyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxtwmkd[yyyyyyyyyyyyyyyyyyyzyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxtxmkd[zzzzzzzzzzzzzzzzzzz{zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzyuynle[{{{{{{{{{{{{{{{{{{{|{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{zvznmf\|||||||||||||||||||}||||||||||||||||||||||||||||||||||||||||||||||||||||{wzomf]}}}}}}}}}}}}}}}}}}}~}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}|x|png^}}}}}}}}}}}}}}}}}}}~}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}|x|pog^~z~rpi_~z~spi`~zsqj`{trka|uska}vslbwumdxundyvoezwpf|xqg}yrh{sj|uk|uk~wmypºººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººypýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýý|sŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽ}tv¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹yŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽý}ƿƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽſƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽƽĻŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽĽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽûĽdub-1.19.0/scripts/win-installer/header.bmp000066400000000000000000000623321360435400500205710ustar00rootroot00000000000000BMd6(9d¼½ýýľľſ»»üĽĽŽƾƿǿ]]¼ýýþĿĿºûüüýſ]]½½Ŀſ¼Ľ]]¾½ž]]ÿ¼ž]]]]yyyhhhggggggggggggggggggffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddcccccccccccccccccccccxxxwvtý]]PPPwwwhhhgggggggggggggggffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddccccccccccccccccccuuuLLLvurſ]]KKKSSSwwwgggggggggggggggffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddcccccccccccccccpppTTT:::usqÿþ]]KKKKKKTTTwwwggggggggggggffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddccccccccccccmmmZZZ;;;:::trp½]]KKKKKKKKKUUUtttgggggggggffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddddddccccccccchhhccc;;;;;;:::tro]]KKKKKKKKKJJJYYYooommmllllllllllllllllllllllllkkkkkkkkkkkkkkkkkkkkkkkkjjjjjjjjjjjjjjjjjjjjjjjjiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiihhhhhhhhhhhhhhhhhhhhhhhhggggggggggggggggggggggggggggggggggggbbb;;;;;;;;;:::sqo]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFFFFEEEEEEEEEEEEDDDDDDDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAAAAAAAAAA@@@@@@@@@@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::sqo]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFFFFEEEEEEEEEEEEDDDDDDDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAAAAAAAAAA@@@@@@@@@@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFFFFEEEEEEEEEEEEDDDDDDDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAAAAAAAAAA@@@@@@@@@@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFFFFEEEEEEEEEEEEDDDDDDDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAAAAAAAAAA@@@@@@@@@@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHIakGDBCEHpFIJFFFFFFEEEEEEEEEEEEDDDDDDDDDEKNEqCB@BD~EYbBBBAAAAAAAAAAAA@@@@@@@@@@@@???BU]C{@>@ACp>CE=========<<<<<<<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIJJG>1(((((+;DGPTEEEEEEEEEEEEDDDEW`B8*(((((2>CuABBAAAAAA@@@@@@@@@Cq>2(((((*8?@U^===<<<<<<<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIal@+((((((((((:EvEEEEEEEEED5((((((((((+?BRYAAA@@@AOV@-((((((((((4A<>?<<<<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIGo8(((((((((((((/EEFFD+(((((((((((((:CYdARZ;(((((((((((((*@>FJ<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJHbo7(((((((((((((((.B+(((((((((((((((;:((((((((((((((((@=?A<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJMN=((((((28974)((((((((((()5787/((((((((((((/8875*((((()B<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJE*((((+?BoGHHGGGGGGC\m?/(((((((((1@AT_CCCCCCADF?w;*((((((((*:=v>BE>>>>>>=MW>2(((((4@U^;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJKK:((((+CHHHHHHGGGGGGGGGGGGFFFD/(((((((1DtCCCCCCCCCCCCBBBBBBBEF?*((((((*>>BE??????>>>>>>>>>>>>@n2(((((A;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJFr/((((AHIIHHHHHHGGGGGGGGGGGGFFFFFFD(((((((FDDDCCCCCCCCCCCCBBBBBBBBBBEF=((((((>>>>>>>>>>>===C}(((((9>>>>>>>>>>>===>GK:((((*Bhx;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJ>((((>HHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFH(((((IDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAA<((((;@@@????????????>>>>>>>>>>>>======B~(((((Bw;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJ<((((AHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFU(((((ZDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAE((((C@@@????????????>>>>>>>>>>>>======Dt(((((@{;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJ<((((AHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFW(((((\DDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAG((((D@@@????????????>>>>>>>>>>>>======Dt(((((@|;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJ=((((>HHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFN(((((]DDDDDDCCCCCCCCCCCCBBBBBBBBBBBBCCCH((((<@@@????????????>>>>>>>>>>>>======A~(((((Bu;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJ?*(((0HgvHHHHHHHHHGGGGGGGGGGGGFFFFFFIdp7(((((\RRRDDDCCCCCCCCCCCCBBBBBBBBBBBBZZZF((((.@q????????????>>>>>>>>>>>>===AXb6((((*Bhx;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJDbv4((((AHIIHHHHHHGGGGGGGGGGGGFFFFFFD((((((]kkkDDDCCCCCCCCCCCCBBBBBBBBBEEErrrE(((((>>>>>>>>>>>===C~(((((9>BE??????>>>>>>>>>>>>Bv/(((((A;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJC~/((((+?BoGHHGGGGGGC`q?-(((((((]hhhooolllMMMCCCCCCCCC\\\tttjjjhhhE((((((*:=v>AD>>>>>>=MX>1(((((4@U^;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJKK>((((((28974)((((((((]hhhhhhjjjssstttsssuuuooohhhhhhhhhE((((((((/8875)((((()B<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJGYb9(((((((((((((((((((]hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhE(((((((((((((((((((@=?A<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIFi{9((((((((((((((((((]hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhE(((((((((((((((((*@>FJ<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIIIIH\e@+(((((((((*6(((((`hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhlllG((((4,((((((((((4A<>?<<<<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIJJG}>1(((((,2(((((*8?@U^===<<<<<<<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHIakGDBCEHl}FHIFFFF|(((((GtDDDJJJ^^^hhhjjjjjjhhheeePPPBBBAAA;((((;@@@???BT\Cy@?@ACp>CE=========<<<<<<<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFF|(((((GtDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAA;((((;@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFF|(((((GtDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAA;((((;@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFH~(((()IuDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAA>((((>@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFHY`:(((?FW^DDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAAi~3((1@n@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::tro]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFFFFEV^A=AEOTDDDDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAAAA@n=<@o@@@@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::trp]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFFFFEEEEEEEEEEEEDDDDDDDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAAAAAAAAAA@@@@@@@@@@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::usp¾þ]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFFFFEEEEEEEEEEEEDDDDDDDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAAAAAAAAAA@@@@@@@@@@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::vtqĿľ]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFFFFEEEEEEEEEEEEDDDDDDDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAAAAAAAAAA@@@@@@@@@@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::wur]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFFFFEEEEEEEEEEEEDDDDDDDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAAAAAAAAAA@@@@@@@@@@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::xvsľ]]KKKKKKKKKJJJJJJJJJJJJIIIIIIIIIIIIHHHHHHHHHHHHGGGGGGGGGGGGFFFFFFFFFFFFEEEEEEEEEEEEDDDDDDDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAAAAAAAAAA@@@@@@@@@@@@????????????>>>>>>>>>>>>============<<<<<<<<<<<<;;;;;;;;;;;;:::ywu]]¾Ŀý]]½Ŀýſ]]½½ýþĿſüľ]]¼ýýþĿĿºûýĽľ]]¼½ýýľľſ»»üĽĽŽƾƿ]]»»üýýþľſ¹¹úûüĽžžƿ]]»»üĽĽžſƿ¸¹úĻĻżƽƾǿ]]dub-1.19.0/scripts/win-installer/installer.nsi000066400000000000000000000111771360435400500213520ustar00rootroot00000000000000SetCompressor /SOLID lzma ;-------------------------------------------------------- ; Defines ;-------------------------------------------------------- ; Options !ifndef Version !define /ifndef Version "0.9.21" !endif !define DubExecPath "..\..\bin" ;-------------------------------------------------------- ; Includes ;-------------------------------------------------------- !include "MUI.nsh" !include "EnvVarUpdate.nsh" ;-------------------------------------------------------- ; General definitions ;-------------------------------------------------------- ; Name of the installer Name "dub Package Manager ${Version}" ; Name of the output file of the installer OutFile "dub-${Version}-setup.exe" ; Where the program will be installed InstallDir "$PROGRAMFILES\dub" ; Take the installation directory from the registry, if possible InstallDirRegKey HKLM "Software\dub" "" ; Prevent installation of a corrupt installer CRCCheck force RequestExecutionLevel admin ;-------------------------------------------------------- ; Interface settings ;-------------------------------------------------------- ;!define MUI_ICON "installer-icon.ico" ;!define MUI_UNICON "uninstaller-icon.ico" ;-------------------------------------------------------- ; Installer pages ;-------------------------------------------------------- !define MUI_WELCOMEFINISHPAGE_BITMAP "banner.bmp" !define MUI_HEADERIMAGE !define MUI_HEADERIMAGE_BITMAP "header.bmp" !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH !insertmacro MUI_UNPAGE_WELCOME !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES !insertmacro MUI_UNPAGE_FINISH ;-------------------------------------------------------- ; The languages ;-------------------------------------------------------- !insertmacro MUI_LANGUAGE "English" ;-------------------------------------------------------- ; Required section: main program files, ; registry entries, etc. ;-------------------------------------------------------- ; Section "dub" DubFiles ; This section is mandatory SectionIn RO SetOutPath $INSTDIR ; Create installation directory CreateDirectory "$INSTDIR" File "${DubExecPath}\dub.exe" File "${DubExecPath}\libcurl.dll" File "${DubExecPath}\libeay32.dll" File "${DubExecPath}\ssleay32.dll" ; Create command line batch file FileOpen $0 "$INSTDIR\dubvars.bat" w FileWrite $0 "@echo.$\n" FileWrite $0 "@echo Setting up environment for using dub from %~dp0$\n" FileWrite $0 "@set PATH=%~dp0;%PATH%$\n" FileClose $0 ; Write installation dir in the registry WriteRegStr HKLM SOFTWARE\dub "Install_Dir" "$INSTDIR" ; Write registry keys to make uninstall from Windows WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\dub" "DisplayName" "dub package manager" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\dub" "UninstallString" '"$INSTDIR\uninstall.exe"' WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\dub" "NoModify" 1 WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\dub" "NoRepair" 1 WriteUninstaller "uninstall.exe" SectionEnd Section "Add to PATH" AddDubToPath ; Add dub directory to path (for all users) ${EnvVarUpdate} $0 "PATH" "A" "HKLM" "$INSTDIR" SectionEnd Section /o "Start menu shortcuts" StartMenuShortcuts CreateDirectory "$SMPROGRAMS\DUB" ; install dub command prompt CreateShortCut "$SMPROGRAMS\DUB\DUB Command Prompt.lnk" '%comspec%' '/k ""$INSTDIR\dubvars.bat""' "" "" SW_SHOWNORMAL "" "Open DUB Command Prompt" CreateShortCut "$SMPROGRAMS\DUB\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 SectionEnd ;-------------------------------------------------------- ; Uninstaller ;-------------------------------------------------------- Section "Uninstall" ; Remove directories to path (for all users) ; (if for the current user, use HKCU) ${un.EnvVarUpdate} $0 "PATH" "R" "HKLM" "$INSTDIR" ; Remove stuff from registry DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\dub" DeleteRegKey HKLM SOFTWARE\dub DeleteRegKey /ifempty HKLM SOFTWARE\dub ; This is for deleting the remembered language of the installation DeleteRegKey HKCU Software\dub DeleteRegKey /ifempty HKCU Software\dub ; Remove the uninstaller Delete $INSTDIR\uninstall.exe ; Remove shortcuts Delete "$SMPROGRAMS\dub\dub Command Prompt.lnk" ; Remove used directories RMDir /r /REBOOTOK "$INSTDIR" RMDir /r /REBOOTOK "$SMPROGRAMS\dub" SectionEnd dub-1.19.0/scripts/win-installer/make_installer.cmd000066400000000000000000000002311360435400500223060ustar00rootroot00000000000000set GITVER=unknown for /f %%i in ('git describe --tags') do set GITVER=%%i "%ProgramFiles(x86)%\NSIS\makensis.exe" "/DVersion=%GITVER:~1%" installer.nsi dub-1.19.0/semaphore-ci.sh000077500000000000000000000030531360435400500152700ustar00rootroot00000000000000#!/bin/bash set -euo pipefail set -x if [ "${D_VERSION:-dmd}" == "gdc" ] ; then echo "GDC unrelated test failures to be fixed" exit 0 # Use the dub-updating fork of the installer script until https://github.com/dlang/installer/pull/301 is merged wget https://raw.githubusercontent.com/wilzbach/installer-dub/master/script/install.sh -O install.dub.sh bash install.dub.sh -a dub dub_path_activate="$(find $HOME/dlang/*/activate | head -1)" rm "${dub_path_activate}" dub_path="$(dirname "$dub_path_activate")" sudo ln -s "${dub_path}/dub" /usr/bin/dub export DMD=gdmd export DC=gdc # It's technically ~"2.076", but Ternary doesn't seem to have been ported and Vibe.d seems to depend on this. # Ternary was added in 2.072: https://dlang.org/phobos/std_typecons.html#.Ternary # However, the nonet tests is done only for > 2.072 export FRONTEND=2.072 sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install -y gdc-9 # fetch the dmd-like wrapper sudo wget https://raw.githubusercontent.com/D-Programming-GDC/GDMD/master/dmd-script -O /usr/bin/gdmd sudo chmod +x /usr/bin/gdmd # DUB requires gdmd sudo ln -s /usr/bin/gdc-9 /usr/bin/gdc # fake install script and create a fake 'activate' script mkdir -p ~/dlang/gdc-9 echo "deactivate(){ echo;}" > ~/dlang/gdc-9/activate else curl --connect-timeout 5 --max-time 10 --retry 5 --retry-delay 1 --retry-max-time 60 https://dlang.org/install.sh | bash -s "$D_VERSION" fi ./travis-ci.sh dub-1.19.0/setup-ldc-windows.sh000066400000000000000000000036621360435400500163070ustar00rootroot00000000000000#!/usr/bin/env bash # sets up LDC for cross-compilation. Source this script, s.t. the new LDC is in PATH LDC_VERSION="1.13.0" ARCH=${ARCH:-32} VERSION=$(git describe --abbrev=0 --tags) OS=windows # Step 0: install ldc if [ ! -f install.sh ] ; then wget https://dlang.org/install.sh fi . $(bash ./install.sh -a "ldc-${LDC_VERSION}") # for the install.sh script only LDC_PATH="$(dirname $(dirname $(which ldc2)))" # Step 1a: download the LDC x64 windows binaries if [ "${ARCH}" == 64 ] && [ ! -d "ldc2-${LDC_VERSION}-windows-x64" ] ; then wget "https://github.com/ldc-developers/ldc/releases/download/v1.13.0/ldc2-${LDC_VERSION}-windows-x64.7z" 7z x "ldc2-${LDC_VERSION}-windows-x64.7z" > /dev/null # Step 2a: Add LDC windows binaries to LDC Linux if [ ! -d "${LDC_PATH}/lib-win64" ] ; then cp -r ldc2-1.13.0-windows-x64/lib "${LDC_PATH}/lib-win64" cat >> "$LDC_PATH"/etc/ldc2.conf < /dev/null # Step 2b: Add LDC windows binaries to LDC Linux if [ ! -d "${LDC_PATH}/lib-win32" ] ; then cp -r ldc2-1.13.0-windows-x86/lib "${LDC_PATH}/lib-win32" cat >> "$LDC_PATH"/etc/ldc2.conf <= 2087) extern(C) __gshared string[] rt_options = [ "gcopt=parallel:0" ]; int main(string[] args) { return runDubCommandLine(args); } dub-1.19.0/source/dub/000077500000000000000000000000001360435400500144265ustar00rootroot00000000000000dub-1.19.0/source/dub/commandline.d000066400000000000000000002245021360435400500170660ustar00rootroot00000000000000/** Defines the behavior of the DUB command line client. Copyright: © 2012-2013 Matthias Dondorff, Copyright © 2012-2016 Sönke Ludwig License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Matthias Dondorff, Sönke Ludwig */ module dub.commandline; import dub.compilers.compiler; import dub.dependency; import dub.dub; import dub.generators.generator; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.url; import dub.package_; import dub.packagemanager; import dub.packagesuppliers; import dub.project; import dub.internal.utils : getDUBVersion, getClosestMatch, getTempFile; import std.algorithm; import std.array; import std.conv; import std.encoding; import std.exception; import std.file; import std.getopt; import std.process; import std.stdio; import std.string; import std.typecons : Tuple, tuple; import std.variant; import std.path: setExtension; /** Retrieves a list of all available commands. Commands are grouped by category. */ CommandGroup[] getCommands() { return [ CommandGroup("Package creation", new InitCommand ), CommandGroup("Build, test and run", new RunCommand, new BuildCommand, new TestCommand, new LintCommand, new GenerateCommand, new DescribeCommand, new CleanCommand, new DustmiteCommand ), CommandGroup("Package management", new FetchCommand, new InstallCommand, new AddCommand, new RemoveCommand, new UninstallCommand, new UpgradeCommand, new AddPathCommand, new RemovePathCommand, new AddLocalCommand, new RemoveLocalCommand, new ListCommand, new SearchCommand, new AddOverrideCommand, new RemoveOverrideCommand, new ListOverridesCommand, new CleanCachesCommand, new ConvertCommand, ) ]; } /** Processes the given command line and executes the appropriate actions. Params: args = This command line argument array as received in `main`. The first entry is considered to be the name of the binary invoked. Returns: Returns the exit code that is supposed to be returned to the system. */ int runDubCommandLine(string[] args) { logDiagnostic("DUB version %s", getDUBVersion()); version(Windows){ // rdmd uses $TEMP to compute a temporary path. since cygwin substitutes backslashes // with slashes, this causes OPTLINK to fail (it thinks path segments are options) // we substitute the other way around here to fix this. environment["TEMP"] = environment["TEMP"].replace("/", "\\"); } // special stdin syntax if (args.length >= 2 && args[1] == "-") { auto path = getTempFile("app", ".d"); stdin.byChunk(4096).joiner.toFile(path.toNativeString()); args = args[0] ~ [path.toNativeString()] ~ args[2..$]; } // create the list of all supported commands CommandGroup[] commands = getCommands(); string[] commandNames = commands.map!(g => g.commands.map!(c => c.name).array).join.array; // Shebang syntax support for files without .d extension if (args.length >= 2 && !args[1].endsWith(".d") && !args[1].startsWith("-") && !commandNames.canFind(args[1])) { if (exists(args[1])) { auto path = getTempFile("app", ".d"); copy(args[1], path.toNativeString()); args[1] = path.toNativeString(); } else if (exists(args[1].setExtension(".d"))) { args[1] = args[1].setExtension(".d"); } } // special single-file package shebang syntax if (args.length >= 2 && args[1].endsWith(".d")) { args = args[0] ~ ["run", "-q", "--temp-build", "--single", args[1], "--"] ~ args[2 ..$]; } // split application arguments from DUB arguments string[] app_args; auto app_args_idx = args.countUntil("--"); if (app_args_idx >= 0) { app_args = args[app_args_idx+1 .. $]; args = args[0 .. app_args_idx]; } args = args[1 .. $]; // strip the application name // handle direct dub options if (args.length) switch (args[0]) { case "--version": showVersion(); return 0; default: break; } // parse general options CommonOptions options; LogLevel loglevel = LogLevel.info; auto common_args = new CommandArgs(args); try { options.prepare(common_args); if (options.vverbose) loglevel = LogLevel.debug_; else if (options.verbose) loglevel = LogLevel.diagnostic; else if (options.vquiet) loglevel = LogLevel.none; else if (options.quiet) loglevel = LogLevel.warn; else if (options.verror) loglevel = LogLevel.error; setLogLevel(loglevel); } catch (Throwable e) { logError("Error processing arguments: %s", e.msg); logDiagnostic("Full exception: %s", e.toString().sanitize); logInfo("Run 'dub help' for usage information."); return 1; } if (options.root_path.empty) options.root_path = getcwd(); else { import std.path : absolutePath, buildNormalizedPath; options.root_path = options.root_path.absolutePath.buildNormalizedPath; } // extract the command string cmdname; args = common_args.extractRemainingArgs(); if (args.length >= 1 && !args[0].startsWith("-")) { cmdname = args[0]; args = args[1 .. $]; } else { if (options.help) { showHelp(commands, common_args); return 0; } cmdname = "run"; } auto command_args = new CommandArgs(args); if (cmdname == "help") { showHelp(commands, common_args); return 0; } // find the selected command Command cmd; foreach (grp; commands) foreach (c; grp.commands) if (c.name == cmdname) { cmd = c; break; } if (!cmd) { logError("Unknown command: %s", cmdname); writeln(); showHelp(commands, common_args); return 1; } // process command line options for the selected command try { cmd.prepare(command_args); enforceUsage(cmd.acceptsAppArgs || app_args.length == 0, cmd.name ~ " doesn't accept application arguments."); } catch (Throwable e) { logError("Error processing arguments: %s", e.msg); logDiagnostic("Full exception: %s", e.toString().sanitize); logInfo("Run 'dub help' for usage information."); return 1; } if (options.help) { showCommandHelp(cmd, command_args, common_args); return 0; } auto remaining_args = command_args.extractRemainingArgs(); if (remaining_args.any!(a => a.startsWith("-"))) { logError("Unknown command line flags: %s", remaining_args.filter!(a => a.startsWith("-")).array.join(" ")); logError(`Type "dub %s -h" to get a list of all supported flags.`, cmdname); return 1; } Dub dub; // initialize the root package if (!cmd.skipDubInitialization) { if (options.bare) { dub = new Dub(NativePath(getcwd())); dub.rootPath = NativePath(options.root_path); dub.defaultPlacementLocation = options.placementLocation; } else { // initialize DUB auto package_suppliers = options.registry_urls .map!((url) { // Allow to specify fallback mirrors as space separated urls. Undocumented as we // should simply retry over all registries instead of using a special // FallbackPackageSupplier. auto urls = url.splitter(' '); PackageSupplier ps = getRegistryPackageSupplier(urls.front); urls.popFront; if (!urls.empty) ps = new FallbackPackageSupplier(ps ~ urls.map!getRegistryPackageSupplier.array); return ps; }) .array; dub = new Dub(options.root_path, package_suppliers, options.skipRegistry); dub.dryRun = options.annotate; dub.defaultPlacementLocation = options.placementLocation; // make the CWD package available so that for example sub packages can reference their // parent package. try dub.packageManager.getOrLoadPackage(NativePath(options.root_path)); catch (Exception e) { logDiagnostic("No valid package found in current working directory: %s", e.msg); } } } // execute the command try return cmd.execute(dub, remaining_args, app_args); catch (UsageException e) { logError("%s", e.msg); logDebug("Full exception: %s", e.toString().sanitize); logInfo(`Run "dub %s -h" for more information about the "%s" command.`, cmdname, cmdname); return 1; } catch (Throwable e) { logError("%s", e.msg); logDebug("Full exception: %s", e.toString().sanitize); return 2; } } /** Contains and parses options common to all commands. */ struct CommonOptions { bool verbose, vverbose, quiet, vquiet, verror; bool help, annotate, bare; string[] registry_urls; string root_path; SkipPackageSuppliers skipRegistry = SkipPackageSuppliers.none; PlacementLocation placementLocation = PlacementLocation.user; /// Parses all common options and stores the result in the struct instance. void prepare(CommandArgs args) { args.getopt("h|help", &help, ["Display general or command specific help"]); args.getopt("root", &root_path, ["Path to operate in instead of the current working dir"]); args.getopt("registry", ®istry_urls, [ "Search the given registry URL first when resolving dependencies. Can be specified multiple times. Available registry types:", " DUB: URL to DUB registry (default)", " Maven: URL to Maven repository + group id containing dub packages as artifacts. E.g. mvn+http://localhost:8040/maven/libs-release/dubpackages", ]); args.getopt("skip-registry", &skipRegistry, [ "Sets a mode for skipping the search on certain package registry types:", " none: Search all configured or default registries (default)", " standard: Don't search the main registry (e.g. "~defaultRegistryURLs[0]~")", " configured: Skip all default and user configured registries", " all: Only search registries specified with --registry", ]); args.getopt("annotate", &annotate, ["Do not perform any action, just print what would be done"]); args.getopt("bare", &bare, ["Read only packages contained in the current directory"]); args.getopt("v|verbose", &verbose, ["Print diagnostic output"]); args.getopt("vverbose", &vverbose, ["Print debug output"]); args.getopt("q|quiet", &quiet, ["Only print warnings and errors"]); args.getopt("verror", &verror, ["Only print errors"]); args.getopt("vquiet", &vquiet, ["Print no messages"]); args.getopt("cache", &placementLocation, ["Puts any fetched packages in the specified location [local|system|user]."]); } } /** Encapsulates a set of application arguments. This class serves two purposes. The first is to provide an API for parsing command line arguments (`getopt`). At the same time it records all calls to `getopt` and provides a list of all possible options using the `recognizedArgs` property. */ class CommandArgs { struct Arg { Variant defaultValue; Variant value; string names; string[] helpText; } private { string[] m_args; Arg[] m_recognizedArgs; } /** Initializes the list of source arguments. Note that all array entries are considered application arguments (i.e. no application name entry is present as the first entry) */ this(string[] args) { m_args = "dummy" ~ args; } /** Returns the list of all options recognized. This list is created by recording all calls to `getopt`. */ @property const(Arg)[] recognizedArgs() { return m_recognizedArgs; } void getopt(T)(string names, T* var, string[] help_text = null) { foreach (ref arg; m_recognizedArgs) if (names == arg.names) { assert(help_text is null); *var = arg.value.get!T; return; } assert(help_text.length > 0); Arg arg; arg.defaultValue = *var; arg.names = names; arg.helpText = help_text; m_args.getopt(config.passThrough, names, var); arg.value = *var; m_recognizedArgs ~= arg; } /** Resets the list of available source arguments. */ void dropAllArgs() { m_args = null; } /** Returns the list of unprocessed arguments and calls `dropAllArgs`. */ string[] extractRemainingArgs() { auto ret = m_args[1 .. $]; m_args = null; return ret; } } /** Base class for all commands. This cass contains a high-level description of the command, including brief and full descriptions and a human readable command line pattern. On top of that it defines the two main entry functions for command execution. */ class Command { string name; string argumentsPattern; string description; string[] helpText; bool acceptsAppArgs; bool hidden = false; // used for deprecated commands bool skipDubInitialization = false; /** Parses all known command line options without executing any actions. This function will be called prior to execute, or may be called as the only method when collecting the list of recognized command line options. Only `args.getopt` should be called within this method. */ abstract void prepare(scope CommandArgs args); /** Executes the actual action. Note that `prepare` will be called before any call to `execute`. */ abstract int execute(Dub dub, string[] free_args, string[] app_args); private bool loadCwdPackage(Dub dub, bool warn_missing_package) { bool found = existsFile(dub.rootPath ~ "source/app.d"); if (!found) foreach (f; packageInfoFiles) if (existsFile(dub.rootPath ~ f.filename)) { found = true; break; } if (!found) { if (warn_missing_package) { logInfo(""); logInfo("Neither a package description file, nor source/app.d was found in"); logInfo(dub.rootPath.toNativeString()); logInfo("Please run DUB from the root directory of an existing package, or run"); logInfo("\"dub init --help\" to get information on creating a new package."); logInfo(""); } return false; } dub.loadPackage(); return true; } } /** Encapsulates a group of commands that fit into a common category. */ struct CommandGroup { /// Caption of the command category string caption; /// List of commands contained inthis group Command[] commands; this(string caption, Command[] commands...) { this.caption = caption; this.commands = commands.dup; } } /******************************************************************************/ /* INIT */ /******************************************************************************/ class InitCommand : Command { private{ string m_templateType = "minimal"; PackageFormat m_format = PackageFormat.json; bool m_nonInteractive; } this() { this.name = "init"; this.argumentsPattern = "[ [...]]"; this.description = "Initializes an empty package skeleton"; this.helpText = [ "Initializes an empty package of the specified type in the given directory. By default, the current working directory is used." ]; this.acceptsAppArgs = true; } override void prepare(scope CommandArgs args) { args.getopt("t|type", &m_templateType, [ "Set the type of project to generate. Available types:", "", "minimal - simple \"hello world\" project (default)", "vibe.d - minimal HTTP server based on vibe.d", "deimos - skeleton for C header bindings", "custom - custom project provided by dub package", ]); args.getopt("f|format", &m_format, [ "Sets the format to use for the package description file. Possible values:", " " ~ [__traits(allMembers, PackageFormat)].map!(f => f == m_format.init.to!string ? f ~ " (default)" : f).join(", ") ]); args.getopt("n|non-interactive", &m_nonInteractive, ["Don't enter interactive mode."]); } override int execute(Dub dub, string[] free_args, string[] app_args) { string dir; if (free_args.length) { dir = free_args[0]; free_args = free_args[1 .. $]; } static string input(string caption, string default_value) { writef("%s [%s]: ", caption, default_value); auto inp = readln(); return inp.length > 1 ? inp[0 .. $-1] : default_value; } void depCallback(ref PackageRecipe p, ref PackageFormat fmt) { import std.datetime: Clock; if (m_nonInteractive) return; while (true) { string rawfmt = input("Package recipe format (sdl/json)", fmt.to!string); if (!rawfmt.length) break; try { fmt = rawfmt.to!PackageFormat; break; } catch (Exception) { logError("Invalid format, \""~rawfmt~"\", enter either \"sdl\" or \"json\"."); } } auto author = p.authors.join(", "); while (true) { // Tries getting the name until a valid one is given. import std.regex; auto nameRegex = regex(`^[a-z0-9\-_]+$`); string triedName = input("Name", p.name); if (triedName.matchFirst(nameRegex).empty) { logError("Invalid name, \""~triedName~"\", names should consist only of lowercase alphanumeric characters, - and _."); } else { p.name = triedName; break; } } p.description = input("Description", p.description); p.authors = input("Author name", author).split(",").map!(a => a.strip).array; p.license = input("License", p.license); string copyrightString = .format("Copyright © %s, %-(%s, %)", Clock.currTime().year, p.authors); p.copyright = input("Copyright string", copyrightString); while (true) { auto depspec = input("Add dependency (leave empty to skip)", null); if (!depspec.length) break; addDependency(dub, p, depspec); } } if (!["vibe.d", "deimos", "minimal"].canFind(m_templateType)) { free_args ~= m_templateType; } dub.createEmptyPackage(NativePath(dir), free_args, m_templateType, m_format, &depCallback, app_args); logInfo("Package successfully created in %s", dir.length ? dir : "."); return 0; } } /******************************************************************************/ /* GENERATE / BUILD / RUN / TEST / DESCRIBE */ /******************************************************************************/ abstract class PackageBuildCommand : Command { protected { string m_buildType; BuildMode m_buildMode; string m_buildConfig; string m_compilerName; string m_arch; string[] m_debugVersions; string[] m_overrideConfigs; Compiler m_compiler; BuildPlatform m_buildPlatform; BuildSettings m_buildSettings; string m_defaultConfig; bool m_nodeps; bool m_forceRemove = false; bool m_single; bool m_filterVersions = false; } override void prepare(scope CommandArgs args) { args.getopt("b|build", &m_buildType, [ "Specifies the type of build to perform. Note that setting the DFLAGS environment variable will override the build type with custom flags.", "Possible names:", " debug (default), plain, release, release-debug, release-nobounds, unittest, profile, profile-gc, docs, ddox, cov, unittest-cov, syntax and custom types" ]); args.getopt("c|config", &m_buildConfig, [ "Builds the specified configuration. Configurations can be defined in dub.json" ]); args.getopt("override-config", &m_overrideConfigs, [ "Uses the specified configuration for a certain dependency. Can be specified multiple times.", "Format: --override-config=/" ]); args.getopt("compiler", &m_compilerName, [ "Specifies the compiler binary to use (can be a path).", "Arbitrary pre- and suffixes to the identifiers below are recognized (e.g. ldc2 or dmd-2.063) and matched to the proper compiler type:", " "~["dmd", "gdc", "ldc", "gdmd", "ldmd"].join(", ") ]); args.getopt("a|arch", &m_arch, [ "Force a different architecture (e.g. x86 or x86_64)" ]); args.getopt("d|debug", &m_debugVersions, [ "Define the specified debug version identifier when building - can be used multiple times" ]); args.getopt("nodeps", &m_nodeps, [ "Do not resolve missing dependencies before building" ]); args.getopt("build-mode", &m_buildMode, [ "Specifies the way the compiler and linker are invoked. Valid values:", " separate (default), allAtOnce, singleFile" ]); args.getopt("single", &m_single, [ "Treats the package name as a filename. The file must contain a package recipe comment." ]); args.getopt("force-remove", &m_forceRemove, [ "Deprecated option that does nothing." ]); args.getopt("filter-versions", &m_filterVersions, [ "[Experimental] Filter version identifiers and debug version identifiers to improve build cache efficiency." ]); } protected void setupPackage(Dub dub, string package_name, string default_build_type = "debug") { if (!m_compilerName.length) m_compilerName = dub.defaultCompiler; if (!m_arch.length) m_arch = dub.defaultArchitecture; m_compiler = getCompiler(m_compilerName); m_buildPlatform = m_compiler.determinePlatform(m_buildSettings, m_compilerName, m_arch); m_buildSettings.addDebugVersions(m_debugVersions); m_defaultConfig = null; enforce (loadSpecificPackage(dub, package_name), "Failed to load package."); if (m_buildConfig.length != 0 && !dub.configurations.canFind(m_buildConfig)) { string msg = "Unknown build configuration: "~m_buildConfig; enum distance = 3; auto match = dub.configurations.getClosestMatch(m_buildConfig, distance); if (match !is null) msg ~= ". Did you mean '" ~ match ~ "'?"; enforce(0, msg); } if (m_buildType.length == 0) { if (environment.get("DFLAGS") !is null) m_buildType = "$DFLAGS"; else m_buildType = default_build_type; } if (!m_nodeps) { // retrieve missing packages dub.project.reinit(); if (!dub.project.hasAllDependencies) { logDiagnostic("Checking for missing dependencies."); if (m_single) dub.upgrade(UpgradeOptions.select | UpgradeOptions.noSaveSelections); else dub.upgrade(UpgradeOptions.select); } } dub.project.validate(); foreach (sc; m_overrideConfigs) { auto idx = sc.indexOf('/'); enforceUsage(idx >= 0, "Expected \"/\" as argument to --override-config."); dub.project.overrideConfiguration(sc[0 .. idx], sc[idx+1 .. $]); } } private bool loadSpecificPackage(Dub dub, string package_name) { if (m_single) { enforce(package_name.length, "Missing file name of single-file package."); dub.loadSingleFilePackage(package_name); return true; } bool from_cwd = package_name.length == 0 || package_name.startsWith(":"); // load package in root_path to enable searching for sub packages if (loadCwdPackage(dub, from_cwd)) { if (package_name.startsWith(":")) { auto pack = dub.packageManager.getSubPackage(dub.project.rootPackage, package_name[1 .. $], false); dub.loadPackage(pack); return true; } if (from_cwd) return true; } enforce(package_name.length, "No valid root package found - aborting."); auto pack = dub.packageManager.getFirstPackage(package_name); enforce(pack, "Failed to find a package named '"~package_name~"' locally."); logInfo("Building package %s in %s", pack.name, pack.path.toNativeString()); dub.rootPath = pack.path; dub.loadPackage(pack); return true; } } class GenerateCommand : PackageBuildCommand { protected { string m_generator; bool m_rdmd = false; bool m_tempBuild = false; bool m_run = false; bool m_force = false; bool m_combined = false; bool m_parallel = false; bool m_printPlatform, m_printBuilds, m_printConfigs; } this() { this.name = "generate"; this.argumentsPattern = " []"; this.description = "Generates project files using the specified generator"; this.helpText = [ "Generates project files using one of the supported generators:", "", "visuald - VisualD project files", "sublimetext - SublimeText project file", "cmake - CMake build scripts", "build - Builds the package directly", "", "An optional package name can be given to generate a different package than the root/CWD package." ]; } override void prepare(scope CommandArgs args) { super.prepare(args); args.getopt("combined", &m_combined, [ "Tries to build the whole project in a single compiler run." ]); args.getopt("print-builds", &m_printBuilds, [ "Prints the list of available build types" ]); args.getopt("print-configs", &m_printConfigs, [ "Prints the list of available configurations" ]); args.getopt("print-platform", &m_printPlatform, [ "Prints the identifiers for the current build platform as used for the build fields in dub.json" ]); args.getopt("parallel", &m_parallel, [ "Runs multiple compiler instances in parallel, if possible." ]); } override int execute(Dub dub, string[] free_args, string[] app_args) { string package_name; if (!m_generator.length) { enforceUsage(free_args.length >= 1 && free_args.length <= 2, "Expected one or two arguments."); m_generator = free_args[0]; if (free_args.length >= 2) package_name = free_args[1]; } else { enforceUsage(free_args.length <= 1, "Expected one or zero arguments."); if (free_args.length >= 1) package_name = free_args[0]; } setupPackage(dub, package_name); if (m_printBuilds) { // FIXME: use actual package data logInfo("Available build types:"); foreach (tp; ["debug", "release", "unittest", "profile"]) logInfo(" %s", tp); logInfo(""); } m_defaultConfig = dub.project.getDefaultConfiguration(m_buildPlatform); if (m_printConfigs) { logInfo("Available configurations:"); foreach (tp; dub.configurations) logInfo(" %s%s", tp, tp == m_defaultConfig ? " [default]" : null); logInfo(""); } GeneratorSettings gensettings; gensettings.platform = m_buildPlatform; gensettings.config = m_buildConfig.length ? m_buildConfig : m_defaultConfig; gensettings.buildType = m_buildType; gensettings.buildMode = m_buildMode; gensettings.compiler = m_compiler; gensettings.buildSettings = m_buildSettings; gensettings.combined = m_combined; gensettings.filterVersions = m_filterVersions; gensettings.run = m_run; gensettings.runArgs = app_args; gensettings.force = m_force; gensettings.rdmd = m_rdmd; gensettings.tempBuild = m_tempBuild; gensettings.parallelBuild = m_parallel; gensettings.single = m_single; logDiagnostic("Generating using %s", m_generator); dub.generateProject(m_generator, gensettings); if (m_buildType == "ddox") dub.runDdox(gensettings.run, app_args); return 0; } } class BuildCommand : GenerateCommand { protected { bool m_yes; // automatic yes to prompts; bool m_nonInteractive; } this() { this.name = "build"; this.argumentsPattern = "[]"; this.description = "Builds a package (uses the main package in the current working directory by default)"; this.helpText = [ "Builds a package (uses the main package in the current working directory by default)" ]; } override void prepare(scope CommandArgs args) { args.getopt("rdmd", &m_rdmd, [ "Use rdmd instead of directly invoking the compiler" ]); args.getopt("f|force", &m_force, [ "Forces a recompilation even if the target is up to date" ]); args.getopt("y|yes", &m_yes, [ `Automatic yes to prompts. Assume "yes" as answer to all interactive prompts.` ]); args.getopt("n|non-interactive", &m_nonInteractive, [ "Don't enter interactive mode." ]); super.prepare(args); m_generator = "build"; } override int execute(Dub dub, string[] free_args, string[] app_args) { // single package files don't need to be downloaded, they are on the disk. if (free_args.length < 1 || m_single) return super.execute(dub, free_args, app_args); if (!m_nonInteractive) { const packageParts = splitPackageName(free_args[0]); if (auto rc = fetchMissingPackages(dub, packageParts)) return rc; free_args[0] = packageParts.name; } return super.execute(dub, free_args, app_args); } private int fetchMissingPackages(Dub dub, in PackageAndVersion packageParts) { static bool input(string caption, bool default_value = true) { writef("%s [%s]: ", caption, default_value ? "Y/n" : "y/N"); auto inp = readln(); string userInput = "y"; if (inp.length > 1) userInput = inp[0 .. $ - 1].toLower; switch (userInput) { case "no", "n", "0": return false; case "yes", "y", "1": default: return true; } } Dependency dep; if (packageParts.version_.length > 0) { // the user provided a version manually dep = Dependency(packageParts.version_); } else { if (packageParts.name.startsWith(":") || dub.packageManager.getFirstPackage(packageParts.name)) // found locally return 0; // search for the package and filter versions for exact matches auto basePackageName = getBasePackageName(packageParts.name); auto search = dub.searchPackages(basePackageName) .map!(tup => tup[1].find!(p => p.name == basePackageName)) .filter!(ps => !ps.empty); if (search.empty) { logWarn("Package '%s' was neither found locally nor online.", packageParts.name); return 2; } const p = search.front.front; logInfo("Package '%s' was not found locally but is available online:", packageParts.name); logInfo("---"); logInfo("Description: %s", p.description); logInfo("Version: %s", p.version_); logInfo("---"); const answer = m_yes ? true : input("Do you want to fetch '%s' now?".format(packageParts.name)); if (!answer) return 0; dep = Dependency(p.version_); } dub.fetch(packageParts.name, dep, dub.defaultPlacementLocation, FetchOptions.none); return 0; } } class RunCommand : BuildCommand { this() { this.name = "run"; this.argumentsPattern = "[]"; this.description = "Builds and runs a package (default command)"; this.helpText = [ "Builds and runs a package (uses the main package in the current working directory by default)" ]; this.acceptsAppArgs = true; } override void prepare(scope CommandArgs args) { args.getopt("temp-build", &m_tempBuild, [ "Builds the project in the temp folder if possible." ]); super.prepare(args); m_run = true; } override int execute(Dub dub, string[] free_args, string[] app_args) { return super.execute(dub, free_args, app_args); } } class TestCommand : PackageBuildCommand { private { string m_mainFile; bool m_combined = false; bool m_parallel = false; bool m_force = false; } this() { this.name = "test"; this.argumentsPattern = "[]"; this.description = "Executes the tests of the selected package"; this.helpText = [ `Builds the package and executes all contained unit tests.`, ``, `If no explicit configuration is given, an existing "unittest" ` ~ `configuration will be preferred for testing. If none exists, the ` ~ `first library type configuration will be used, and if that doesn't ` ~ `exist either, the first executable configuration is chosen.`, ``, `When a custom main file (--main-file) is specified, only library ` ~ `configurations can be used. Otherwise, depending on the type of ` ~ `the selected configuration, either an existing main file will be ` ~ `used (and needs to be properly adjusted to just run the unit ` ~ `tests for 'version(unittest)'), or DUB will generate one for ` ~ `library type configurations.`, ``, `Finally, if the package contains a dependency to the "tested" ` ~ `package, the automatically generated main file will use it to ` ~ `run the unit tests.` ]; this.acceptsAppArgs = true; } override void prepare(scope CommandArgs args) { args.getopt("main-file", &m_mainFile, [ "Specifies a custom file containing the main() function to use for running the tests." ]); args.getopt("combined", &m_combined, [ "Tries to build the whole project in a single compiler run." ]); args.getopt("parallel", &m_parallel, [ "Runs multiple compiler instances in parallel, if possible." ]); args.getopt("f|force", &m_force, [ "Forces a recompilation even if the target is up to date" ]); bool coverage = false; args.getopt("coverage", &coverage, [ "Enables code coverage statistics to be generated." ]); if (coverage) m_buildType = "unittest-cov"; super.prepare(args); } override int execute(Dub dub, string[] free_args, string[] app_args) { string package_name; enforceUsage(free_args.length <= 1, "Expected one or zero arguments."); if (free_args.length >= 1) package_name = free_args[0]; setupPackage(dub, package_name, "unittest"); GeneratorSettings settings; settings.platform = m_buildPlatform; settings.compiler = getCompiler(m_buildPlatform.compilerBinary); settings.buildType = m_buildType; settings.buildMode = m_buildMode; settings.buildSettings = m_buildSettings; settings.combined = m_combined; settings.filterVersions = m_filterVersions; settings.parallelBuild = m_parallel; settings.force = m_force; settings.tempBuild = m_single; settings.run = true; settings.runArgs = app_args; dub.testProject(settings, m_buildConfig, NativePath(m_mainFile)); return 0; } } class LintCommand : PackageBuildCommand { private { bool m_syntaxCheck = false; bool m_styleCheck = false; string m_errorFormat; bool m_report = false; string m_reportFormat; string[] m_importPaths; string m_config; } this() { this.name = "lint"; this.argumentsPattern = "[]"; this.description = "Executes the linter tests of the selected package"; this.helpText = [ `Builds the package and executes D-Scanner linter tests.` ]; this.acceptsAppArgs = true; } override void prepare(scope CommandArgs args) { args.getopt("syntax-check", &m_syntaxCheck, [ "Lexes and parses sourceFile, printing the line and column number of " ~ "any syntax errors to stdout." ]); args.getopt("style-check", &m_styleCheck, [ "Lexes and parses sourceFiles, printing the line and column number of " ~ "any static analysis check failures stdout." ]); args.getopt("error-format", &m_errorFormat, [ "Format errors produced by the style/syntax checkers." ]); args.getopt("report", &m_report, [ "Generate a static analysis report in JSON format." ]); args.getopt("report-format", &m_reportFormat, [ "Specifies the format of the generated report." ]); if (m_reportFormat) m_report = true; args.getopt("import-paths", &m_importPaths, [ "Import paths" ]); args.getopt("config", &m_config, [ "Use the given configuration file." ]); super.prepare(args); } override int execute(Dub dub, string[] free_args, string[] app_args) { string package_name; enforceUsage(free_args.length <= 1, "Expected one or zero arguments."); if (free_args.length >= 1) package_name = free_args[0]; string[] args; if (!m_syntaxCheck && !m_styleCheck && !m_report && app_args.length == 0) { m_styleCheck = true; } if (m_syntaxCheck) args ~= "--syntaxCheck"; if (m_styleCheck) args ~= "--styleCheck"; if (m_errorFormat) args ~= ["--errorFormat", m_errorFormat]; if (m_report) args ~= "--report"; if (m_reportFormat) args ~= ["--reportFormat", m_reportFormat]; foreach (import_path; m_importPaths) args ~= ["-I", import_path]; if (m_config) args ~= ["--config", m_config]; setupPackage(dub, package_name); dub.lintProject(args ~ app_args); return 0; } } class DescribeCommand : PackageBuildCommand { private { bool m_importPaths = false; bool m_stringImportPaths = false; bool m_dataList = false; bool m_dataNullDelim = false; string[] m_data; } this() { this.name = "describe"; this.argumentsPattern = "[]"; this.description = "Prints a JSON description of the project and its dependencies"; this.helpText = [ "Prints a JSON build description for the root package an all of " ~ "their dependencies in a format similar to a JSON package " ~ "description file. This is useful mostly for IDEs.", "", "All usual options that are also used for build/run/generate apply.", "", "When --data=VALUE is supplied, specific build settings for a project " ~ "will be printed instead (by default, formatted for the current compiler).", "", "The --data=VALUE option can be specified multiple times to retrieve " ~ "several pieces of information at once. A comma-separated list is " ~ "also acceptable (ex: --data=dflags,libs). The data will be output in " ~ "the same order requested on the command line.", "", "The accepted values for --data=VALUE are:", "", "main-source-file, dflags, lflags, libs, linker-files, " ~ "source-files, versions, debug-versions, import-paths, " ~ "string-import-paths, import-files, options", "", "The following are also accepted by --data if --data-list is used:", "", "target-type, target-path, target-name, working-directory, " ~ "copy-files, string-import-files, pre-generate-commands, " ~ "post-generate-commands, pre-build-commands, post-build-commands, " ~ "requirements", ]; } override void prepare(scope CommandArgs args) { super.prepare(args); args.getopt("import-paths", &m_importPaths, [ "Shortcut for --data=import-paths --data-list" ]); args.getopt("string-import-paths", &m_stringImportPaths, [ "Shortcut for --data=string-import-paths --data-list" ]); args.getopt("data", &m_data, [ "Just list the values of a particular build setting, either for this "~ "package alone or recursively including all dependencies. Accepts a "~ "comma-separated list. See above for more details and accepted "~ "possibilities for VALUE." ]); args.getopt("data-list", &m_dataList, [ "Output --data information in list format (line-by-line), instead "~ "of formatting for a compiler command line.", ]); args.getopt("data-0", &m_dataNullDelim, [ "Output --data information using null-delimiters, rather than "~ "spaces or newlines. Result is usable with, ex., xargs -0.", ]); } override int execute(Dub dub, string[] free_args, string[] app_args) { enforceUsage( !(m_importPaths && m_stringImportPaths), "--import-paths and --string-import-paths may not be used together." ); enforceUsage( !(m_data && (m_importPaths || m_stringImportPaths)), "--data may not be used together with --import-paths or --string-import-paths." ); // disable all log output to stdout and use "writeln" to output the JSON description auto ll = getLogLevel(); setLogLevel(max(ll, LogLevel.warn)); scope (exit) setLogLevel(ll); string package_name; enforceUsage(free_args.length <= 1, "Expected one or zero arguments."); if (free_args.length >= 1) package_name = free_args[0]; setupPackage(dub, package_name); m_defaultConfig = dub.project.getDefaultConfiguration(m_buildPlatform); auto config = m_buildConfig.length ? m_buildConfig : m_defaultConfig; GeneratorSettings settings; settings.platform = m_buildPlatform; settings.config = config; settings.buildType = m_buildType; settings.compiler = m_compiler; settings.filterVersions = m_filterVersions; if (m_importPaths) { m_data = ["import-paths"]; m_dataList = true; } else if (m_stringImportPaths) { m_data = ["string-import-paths"]; m_dataList = true; } if (m_data.length) { ListBuildSettingsFormat lt; with (ListBuildSettingsFormat) lt = m_dataList ? (m_dataNullDelim ? listNul : list) : (m_dataNullDelim ? commandLineNul : commandLine); dub.listProjectData(settings, m_data, lt); } else { auto desc = dub.project.describe(settings); writeln(desc.serializeToPrettyJson()); } return 0; } } class CleanCommand : Command { private { bool m_allPackages; } this() { this.name = "clean"; this.argumentsPattern = "[]"; this.description = "Removes intermediate build files and cached build results"; this.helpText = [ "This command removes any cached build files of the given package(s). The final target file, as well as any copyFiles are currently not removed.", "Without arguments, the package in the current working directory will be cleaned." ]; } override void prepare(scope CommandArgs args) { args.getopt("all-packages", &m_allPackages, [ "Cleans up *all* known packages (dub list)" ]); } override int execute(Dub dub, string[] free_args, string[] app_args) { enforceUsage(free_args.length <= 1, "Expected one or zero arguments."); enforceUsage(app_args.length == 0, "Application arguments are not supported for the clean command."); enforceUsage(!m_allPackages || !free_args.length, "The --all-packages flag may not be used together with an explicit package name."); enforce(free_args.length == 0, "Cleaning a specific package isn't possible right now."); if (m_allPackages) { bool any_error = false; foreach (p; dub.packageManager.getPackageIterator()) { try dub.cleanPackage(p.path); catch (Exception e) { logWarn("Failed to clean package %s at %s: %s", p.name, p.path, e.msg); any_error = true; } foreach (sp; p.subPackages.filter!(sp => !sp.path.empty)) { try dub.cleanPackage(p.path ~ sp.path); catch (Exception e) { logWarn("Failed to clean sub package of %s at %s: %s", p.name, p.path ~ sp.path, e.msg); any_error = true; } } } if (any_error) return 1; } else { dub.cleanPackage(dub.rootPath); } return 0; } } /******************************************************************************/ /* FETCH / ADD / REMOVE / UPGRADE */ /******************************************************************************/ class AddCommand : Command { this() { this.name = "add"; this.argumentsPattern = "[@] []"; this.description = "Adds dependencies to the package file."; this.helpText = [ "Adds as dependencies.", "", "Running \"dub add \" is the same as adding to the \"dependencies\" section in dub.json/dub.sdl.", "If no version is specified for one of the packages, dub will query the registry for the latest version." ]; } override void prepare(scope CommandArgs args) {} override int execute(Dub dub, string[] free_args, string[] app_args) { import dub.recipe.io : readPackageRecipe, writePackageRecipe; import dub.internal.vibecompat.core.file : existsFile; enforceUsage(free_args.length != 0, "Expected one or more arguments."); enforceUsage(app_args.length == 0, "Unexpected application arguments."); if (!loadCwdPackage(dub, true)) return 1; auto recipe = dub.project.rootPackage.rawRecipe.clone; foreach (depspec; free_args) { if (!addDependency(dub, recipe, depspec)) return 1; } writePackageRecipe(dub.project.rootPackage.recipePath, recipe); return 0; } } class UpgradeCommand : Command { private { bool m_prerelease = false; bool m_forceRemove = false; bool m_missingOnly = false; bool m_verify = false; bool m_dryRun = false; } this() { this.name = "upgrade"; this.argumentsPattern = "[]"; this.description = "Forces an upgrade of the dependencies"; this.helpText = [ "Upgrades all dependencies of the package by querying the package registry(ies) for new versions.", "", "This will update the versions stored in the selections file ("~SelectedVersions.defaultFile~") accordingly.", "", "If one or more package names are specified, only those dependencies will be upgraded. Otherwise all direct and indirect dependencies of the root package will get upgraded." ]; } override void prepare(scope CommandArgs args) { args.getopt("prerelease", &m_prerelease, [ "Uses the latest pre-release version, even if release versions are available" ]); args.getopt("verify", &m_verify, [ "Updates the project and performs a build. If successful, rewrites the selected versions file ." ]); args.getopt("dry-run", &m_dryRun, [ "Only print what would be upgraded, but don't actually upgrade anything." ]); args.getopt("missing-only", &m_missingOnly, [ "Performs an upgrade only for dependencies that don't yet have a version selected. This is also done automatically before each build." ]); args.getopt("force-remove", &m_forceRemove, [ "Deprecated option that does nothing." ]); } override int execute(Dub dub, string[] free_args, string[] app_args) { enforceUsage(free_args.length <= 1, "Unexpected arguments."); enforceUsage(app_args.length == 0, "Unexpected application arguments."); enforceUsage(!m_verify, "--verify is not yet implemented."); dub.loadPackage(); logInfo("Upgrading project in %s", dub.projectPath.toNativeString()); auto options = UpgradeOptions.upgrade|UpgradeOptions.select; if (m_missingOnly) options &= ~UpgradeOptions.upgrade; if (m_prerelease) options |= UpgradeOptions.preRelease; if (m_dryRun) options |= UpgradeOptions.dryRun; dub.upgrade(options, free_args); return 0; } } class FetchRemoveCommand : Command { protected { string m_version; bool m_forceRemove = false; } override void prepare(scope CommandArgs args) { args.getopt("version", &m_version, [ "Use the specified version/branch instead of the latest available match", "The remove command also accepts \"*\" here as a wildcard to remove all versions of the package from the specified location" ]); args.getopt("force-remove", &m_forceRemove, [ "Deprecated option that does nothing" ]); } abstract override int execute(Dub dub, string[] free_args, string[] app_args); } class FetchCommand : FetchRemoveCommand { this() { this.name = "fetch"; this.argumentsPattern = "[@]"; this.description = "Manually retrieves and caches a package"; this.helpText = [ "Note: Use \"dub add \" if you just want to use a certain package as a dependency, you don't have to explicitly fetch packages.", "", "Explicit retrieval/removal of packages is only needed when you want to put packages in a place where several applications can share them. If you just have a dependency to add, use the `add` command. Dub will do the rest for you.", "", "Without specified options, placement/removal will default to a user wide shared location.", "", "Complete applications can be retrieved and run easily by e.g.", "$ dub fetch vibelog --cache=local", "$ cd vibelog", "$ dub", "", "This will grab all needed dependencies and compile and run the application.", "", "Note: DUB does not do a system installation of packages. Packages are instead only registered within DUB's internal ecosystem. Generation of native system packages/installers may be added later as a separate feature." ]; } override void prepare(scope CommandArgs args) { super.prepare(args); } override int execute(Dub dub, string[] free_args, string[] app_args) { enforceUsage(free_args.length == 1, "Expecting exactly one argument."); enforceUsage(app_args.length == 0, "Unexpected application arguments."); auto location = dub.defaultPlacementLocation; auto name = free_args[0]; FetchOptions fetchOpts; fetchOpts |= FetchOptions.forceBranchUpgrade; if (m_version.length) dub.fetch(name, Dependency(m_version), location, fetchOpts); else if (name.canFind("@", "=")) { const parts = name.splitPackageName; dub.fetch(parts.name, Dependency(parts.version_), location, fetchOpts); } else { try { dub.fetch(name, Dependency(">=0.0.0"), location, fetchOpts); logInfo( "Please note that you need to use `dub run ` " ~ "or add it to dependencies of your package to actually use/run it. " ~ "dub does not do actual installation of packages outside of its own ecosystem."); } catch(Exception e){ logInfo("Getting a release version failed: %s", e.msg); logInfo("Retry with ~master..."); dub.fetch(name, Dependency("~master"), location, fetchOpts); } } return 0; } } class InstallCommand : FetchCommand { this() { this.name = "install"; hidden = true; } override void prepare(scope CommandArgs args) { super.prepare(args); } override int execute(Dub dub, string[] free_args, string[] app_args) { warnRenamed("install", "fetch"); return super.execute(dub, free_args, app_args); } } class RemoveCommand : FetchRemoveCommand { private { bool m_nonInteractive; } this() { this.name = "remove"; this.argumentsPattern = ""; this.description = "Removes a cached package"; this.helpText = [ "Removes a package that is cached on the local system." ]; } override void prepare(scope CommandArgs args) { super.prepare(args); args.getopt("n|non-interactive", &m_nonInteractive, ["Don't enter interactive mode."]); } override int execute(Dub dub, string[] free_args, string[] app_args) { enforceUsage(free_args.length == 1, "Expecting exactly one argument."); enforceUsage(app_args.length == 0, "Unexpected application arguments."); auto package_id = free_args[0]; auto location = dub.defaultPlacementLocation; size_t resolveVersion(in Package[] packages) { // just remove only package version if (packages.length == 1) return 0; writeln("Select version of '", package_id, "' to remove from location '", location, "':"); foreach (i, pack; packages) writefln("%s) %s", i + 1, pack.version_); writeln(packages.length + 1, ") ", "all versions"); while (true) { writef("> "); auto inp = readln(); if (!inp.length) // Ctrl+D return size_t.max; inp = inp.stripRight; if (!inp.length) // newline or space continue; try { immutable selection = inp.to!size_t - 1; if (selection <= packages.length) return selection; } catch (ConvException e) { } logError("Please enter a number between 1 and %s.", packages.length + 1); } } if (m_nonInteractive || !m_version.empty) dub.remove(package_id, m_version, location); else dub.remove(package_id, location, &resolveVersion); return 0; } } class UninstallCommand : RemoveCommand { this() { this.name = "uninstall"; hidden = true; } override void prepare(scope CommandArgs args) { super.prepare(args); } override int execute(Dub dub, string[] free_args, string[] app_args) { warnRenamed("uninstall", "remove"); return super.execute(dub, free_args, app_args); } } /******************************************************************************/ /* ADD/REMOVE PATH/LOCAL */ /******************************************************************************/ abstract class RegistrationCommand : Command { private { bool m_system; } override void prepare(scope CommandArgs args) { args.getopt("system", &m_system, [ "Register system-wide instead of user-wide" ]); } abstract override int execute(Dub dub, string[] free_args, string[] app_args); } class AddPathCommand : RegistrationCommand { this() { this.name = "add-path"; this.argumentsPattern = ""; this.description = "Adds a default package search path"; this.helpText = [ "Adds a default package search path. All direct sub folders of this path will be searched for package descriptions and will be made available as packages. Using this command has the equivalent effect as calling 'dub add-local' on each of the sub folders manually.", "", "Any packages registered using add-path will be preferred over packages downloaded from the package registry when searching for dependencies during a build operation.", "", "The version of the packages will be determined by one of the following:", " - For GIT working copies, the last tag (git describe) is used to determine the version", " - If the package contains a \"version\" field in the package description, this is used", " - If neither of those apply, \"~master\" is assumed" ]; } override int execute(Dub dub, string[] free_args, string[] app_args) { enforceUsage(free_args.length == 1, "Missing search path."); dub.addSearchPath(free_args[0], m_system); return 0; } } class RemovePathCommand : RegistrationCommand { this() { this.name = "remove-path"; this.argumentsPattern = ""; this.description = "Removes a package search path"; this.helpText = ["Removes a package search path previously added with add-path."]; } override int execute(Dub dub, string[] free_args, string[] app_args) { enforceUsage(free_args.length == 1, "Expected one argument."); dub.removeSearchPath(free_args[0], m_system); return 0; } } class AddLocalCommand : RegistrationCommand { this() { this.name = "add-local"; this.argumentsPattern = " []"; this.description = "Adds a local package directory (e.g. a git repository)"; this.helpText = [ "Adds a local package directory to be used during dependency resolution. This command is useful for registering local packages, such as GIT working copies, that are either not available in the package registry, or are supposed to be overwritten.", "", "The version of the package is either determined automatically (see the \"add-path\" command, or can be explicitly overwritten by passing a version on the command line.", "", "See 'dub add-path -h' for a way to register multiple local packages at once." ]; } override int execute(Dub dub, string[] free_args, string[] app_args) { enforceUsage(free_args.length == 1 || free_args.length == 2, "Expecting one or two arguments."); string ver = free_args.length == 2 ? free_args[1] : null; dub.addLocalPackage(free_args[0], ver, m_system); return 0; } } class RemoveLocalCommand : RegistrationCommand { this() { this.name = "remove-local"; this.argumentsPattern = ""; this.description = "Removes a local package directory"; this.helpText = ["Removes a local package directory"]; } override int execute(Dub dub, string[] free_args, string[] app_args) { enforceUsage(free_args.length >= 1, "Missing package path argument."); enforceUsage(free_args.length <= 1, "Expected the package path to be the only argument."); dub.removeLocalPackage(free_args[0], m_system); return 0; } } class ListCommand : Command { this() { this.name = "list"; this.argumentsPattern = ""; this.description = "Prints a list of all local packages dub is aware of"; this.helpText = [ "Prints a list of all local packages. This includes all cached packages (user or system wide), all packages in the package search paths (\"dub add-path\") and all manually registered packages (\"dub add-local\")." ]; } override void prepare(scope CommandArgs args) {} override int execute(Dub dub, string[] free_args, string[] app_args) { enforceUsage(free_args.length == 0, "Expecting no extra arguments."); enforceUsage(app_args.length == 0, "The list command supports no application arguments."); logInfo("Packages present in the system and known to dub:"); foreach (p; dub.packageManager.getPackageIterator()) logInfo(" %s %s: %s", p.name, p.version_, p.path.toNativeString()); logInfo(""); return 0; } } class SearchCommand : Command { this() { this.name = "search"; this.argumentsPattern = ""; this.description = "Search for available packages."; this.helpText = [ "Search all specified DUB registries for packages matching query." ]; } override void prepare(scope CommandArgs args) {} override int execute(Dub dub, string[] free_args, string[] app_args) { enforce(free_args.length == 1, "Expected one argument."); auto res = dub.searchPackages(free_args[0]); if (res.empty) { logError("No matches found."); return 1; } auto justify = res .map!((descNmatches) => descNmatches[1]) .joiner .map!(m => m.name.length + m.version_.length) .reduce!max + " ()".length; justify += (~justify & 3) + 1; // round to next multiple of 4 foreach (desc, matches; res) { logInfo("==== %s ====", desc); foreach (m; matches) logInfo("%s%s", leftJustify(m.name ~ " (" ~ m.version_ ~ ")", justify), m.description); } return 0; } } /******************************************************************************/ /* OVERRIDES */ /******************************************************************************/ class AddOverrideCommand : Command { private { bool m_system = false; } this() { this.name = "add-override"; this.argumentsPattern = " "; this.description = "Adds a new package override."; this.helpText = [ ]; } override void prepare(scope CommandArgs args) { args.getopt("system", &m_system, [ "Register system-wide instead of user-wide" ]); } override int execute(Dub dub, string[] free_args, string[] app_args) { enforceUsage(app_args.length == 0, "Unexpected application arguments."); enforceUsage(free_args.length == 3, "Expected three arguments, not "~free_args.length.to!string); auto scope_ = m_system ? LocalPackageType.system : LocalPackageType.user; auto pack = free_args[0]; auto ver = Dependency(free_args[1]); if (existsFile(NativePath(free_args[2]))) { auto target = NativePath(free_args[2]); if (!target.absolute) target = NativePath(getcwd()) ~ target; dub.packageManager.addOverride(scope_, pack, ver, target); logInfo("Added override %s %s => %s", pack, ver, target); } else { auto target = Version(free_args[2]); dub.packageManager.addOverride(scope_, pack, ver, target); logInfo("Added override %s %s => %s", pack, ver, target); } return 0; } } class RemoveOverrideCommand : Command { private { bool m_system = false; } this() { this.name = "remove-override"; this.argumentsPattern = " "; this.description = "Removes an existing package override."; this.helpText = [ ]; } override void prepare(scope CommandArgs args) { args.getopt("system", &m_system, [ "Register system-wide instead of user-wide" ]); } override int execute(Dub dub, string[] free_args, string[] app_args) { enforceUsage(app_args.length == 0, "Unexpected application arguments."); enforceUsage(free_args.length == 2, "Expected two arguments, not "~free_args.length.to!string); auto scope_ = m_system ? LocalPackageType.system : LocalPackageType.user; dub.packageManager.removeOverride(scope_, free_args[0], Dependency(free_args[1])); return 0; } } class ListOverridesCommand : Command { this() { this.name = "list-overrides"; this.argumentsPattern = ""; this.description = "Prints a list of all local package overrides"; this.helpText = [ "Prints a list of all overridden packages added via \"dub add-override\"." ]; } override void prepare(scope CommandArgs args) {} override int execute(Dub dub, string[] free_args, string[] app_args) { void printList(in PackageOverride[] overrides, string caption) { if (overrides.length == 0) return; logInfo("# %s", caption); foreach (ovr; overrides) { if (!ovr.targetPath.empty) logInfo("%s %s => %s", ovr.package_, ovr.version_, ovr.targetPath); else logInfo("%s %s => %s", ovr.package_, ovr.version_, ovr.targetVersion); } } printList(dub.packageManager.getOverrides(LocalPackageType.user), "User wide overrides"); printList(dub.packageManager.getOverrides(LocalPackageType.system), "System wide overrides"); return 0; } } /******************************************************************************/ /* Cache cleanup */ /******************************************************************************/ class CleanCachesCommand : Command { this() { this.name = "clean-caches"; this.argumentsPattern = ""; this.description = "Removes cached metadata"; this.helpText = [ "This command removes any cached metadata like the list of available packages and their latest version." ]; } override void prepare(scope CommandArgs args) {} override int execute(Dub dub, string[] free_args, string[] app_args) { return 0; } } /******************************************************************************/ /* DUSTMITE */ /******************************************************************************/ class DustmiteCommand : PackageBuildCommand { private { int m_compilerStatusCode = int.min; int m_linkerStatusCode = int.min; int m_programStatusCode = int.min; string m_compilerRegex; string m_linkerRegex; string m_programRegex; string m_testPackage; bool m_combined; } this() { this.name = "dustmite"; this.argumentsPattern = ""; this.acceptsAppArgs = true; this.description = "Create reduced test cases for build errors"; this.helpText = [ "This command uses the Dustmite utility to isolate the cause of build errors in a DUB project.", "", "It will create a copy of all involved packages and run dustmite on this copy, leaving a reduced test case.", "", "Determining the desired error condition is done by checking the compiler/linker status code, as well as their output (stdout and stderr combined). If --program-status or --program-regex is given and the generated binary is an executable, it will be executed and its output will also be incorporated into the final decision." ]; } override void prepare(scope CommandArgs args) { args.getopt("compiler-status", &m_compilerStatusCode, ["The expected status code of the compiler run"]); args.getopt("compiler-regex", &m_compilerRegex, ["A regular expression used to match against the compiler output"]); args.getopt("linker-status", &m_linkerStatusCode, ["The expected status code of the linker run"]); args.getopt("linker-regex", &m_linkerRegex, ["A regular expression used to match against the linker output"]); args.getopt("program-status", &m_programStatusCode, ["The expected status code of the built executable"]); args.getopt("program-regex", &m_programRegex, ["A regular expression used to match against the program output"]); args.getopt("test-package", &m_testPackage, ["Perform a test run - usually only used internally"]); args.getopt("combined", &m_combined, ["Builds multiple packages with one compiler run"]); super.prepare(args); // speed up loading when in test mode if (m_testPackage.length) { skipDubInitialization = true; m_nodeps = true; } } override int execute(Dub dub, string[] free_args, string[] app_args) { import std.format : formattedWrite; if (m_testPackage.length) { dub = new Dub(NativePath(getcwd())); setupPackage(dub, m_testPackage); m_defaultConfig = dub.project.getDefaultConfiguration(m_buildPlatform); GeneratorSettings gensettings; gensettings.platform = m_buildPlatform; gensettings.config = m_buildConfig.length ? m_buildConfig : m_defaultConfig; gensettings.buildType = m_buildType; gensettings.compiler = m_compiler; gensettings.buildSettings = m_buildSettings; gensettings.combined = m_combined; gensettings.filterVersions = m_filterVersions; gensettings.run = m_programStatusCode != int.min || m_programRegex.length; gensettings.runArgs = app_args; gensettings.force = true; gensettings.compileCallback = check(m_compilerStatusCode, m_compilerRegex); gensettings.linkCallback = check(m_linkerStatusCode, m_linkerRegex); gensettings.runCallback = check(m_programStatusCode, m_programRegex); try dub.generateProject("build", gensettings); catch (DustmiteMismatchException) { logInfo("Dustmite test doesn't match."); return 3; } catch (DustmiteMatchException) { logInfo("Dustmite test matches."); return 0; } } else { enforceUsage(free_args.length == 1, "Expected destination path."); auto path = NativePath(free_args[0]); path.normalize(); enforceUsage(!path.empty, "Destination path must not be empty."); if (!path.absolute) path = NativePath(getcwd()) ~ path; enforceUsage(!path.startsWith(dub.rootPath), "Destination path must not be a sub directory of the tested package!"); setupPackage(dub, null); auto prj = dub.project; if (m_buildConfig.empty) m_buildConfig = prj.getDefaultConfiguration(m_buildPlatform); void copyFolderRec(NativePath folder, NativePath dstfolder) { mkdirRecurse(dstfolder.toNativeString()); foreach (de; iterateDirectory(folder.toNativeString())) { if (de.name.startsWith(".")) continue; if (de.isDirectory) { copyFolderRec(folder ~ de.name, dstfolder ~ de.name); } else { if (de.name.endsWith(".o") || de.name.endsWith(".obj")) continue; if (de.name.endsWith(".exe")) continue; try copyFile(folder ~ de.name, dstfolder ~ de.name); catch (Exception e) { logWarn("Failed to copy file %s: %s", (folder ~ de.name).toNativeString(), e.msg); } } } } static void fixPathDependency(string pack, ref Dependency dep) { if (!dep.path.empty) { auto mainpack = getBasePackageName(pack); dep.path = NativePath("../") ~ mainpack; } } void fixPathDependencies(ref PackageRecipe recipe, NativePath base_path) { foreach (name, ref dep; recipe.buildSettings.dependencies) fixPathDependency(name, dep); foreach (ref cfg; recipe.configurations) foreach (name, ref dep; cfg.buildSettings.dependencies) fixPathDependency(name, dep); foreach (ref subp; recipe.subPackages) if (subp.path.length) { auto sub_path = base_path ~ NativePath(subp.path); auto pack = prj.packageManager.getOrLoadPackage(sub_path); fixPathDependencies(pack.recipe, sub_path); pack.storeInfo(sub_path); } else fixPathDependencies(subp.recipe, base_path); } bool[string] visited; foreach (pack_; prj.getTopologicalPackageList()) { auto pack = pack_.basePackage; if (pack.name in visited) continue; visited[pack.name] = true; auto dst_path = path ~ pack.name; logInfo("Copy package '%s' to destination folder...", pack.name); copyFolderRec(pack.path, dst_path); // adjust all path based dependencies fixPathDependencies(pack.recipe, dst_path); // overwrite package description file with additional version information pack.storeInfo(dst_path); } logInfo("Executing dustmite..."); auto testcmd = appender!string(); testcmd.formattedWrite("%s dustmite --vquiet --test-package=%s --build=%s --config=%s", thisExePath, prj.name, m_buildType, m_buildConfig); if (m_compilerName.length) testcmd.formattedWrite(" \"--compiler=%s\"", m_compilerName); if (m_arch.length) testcmd.formattedWrite(" --arch=%s", m_arch); if (m_compilerStatusCode != int.min) testcmd.formattedWrite(" --compiler-status=%s", m_compilerStatusCode); if (m_compilerRegex.length) testcmd.formattedWrite(" \"--compiler-regex=%s\"", m_compilerRegex); if (m_linkerStatusCode != int.min) testcmd.formattedWrite(" --linker-status=%s", m_linkerStatusCode); if (m_linkerRegex.length) testcmd.formattedWrite(" \"--linker-regex=%s\"", m_linkerRegex); if (m_programStatusCode != int.min) testcmd.formattedWrite(" --program-status=%s", m_programStatusCode); if (m_programRegex.length) testcmd.formattedWrite(" \"--program-regex=%s\"", m_programRegex); if (m_combined) testcmd ~= " --combined"; // TODO: pass *all* original parameters logDiagnostic("Running dustmite: %s", testcmd); auto dmpid = spawnProcess(["dustmite", path.toNativeString(), testcmd.data]); return dmpid.wait(); } return 0; } void delegate(int, string) check(int code_match, string regex_match) { return (code, output) { import std.encoding; import std.regex; logInfo("%s", output); if (code_match != int.min && code != code_match) { logInfo("Exit code %s doesn't match expected value %s", code, code_match); throw new DustmiteMismatchException; } if (regex_match.length > 0 && !match(output.sanitize, regex_match)) { logInfo("Output doesn't match regex:"); logInfo("%s", output); throw new DustmiteMismatchException; } if (code != 0 && code_match != int.min || regex_match.length > 0) { logInfo("Tool failed, but matched either exit code or output - counting as match."); throw new DustmiteMatchException; } }; } static class DustmiteMismatchException : Exception { this(string message = "", string file = __FILE__, int line = __LINE__, Throwable next = null) { super(message, file, line, next); } } static class DustmiteMatchException : Exception { this(string message = "", string file = __FILE__, int line = __LINE__, Throwable next = null) { super(message, file, line, next); } } } /******************************************************************************/ /* CONVERT command */ /******************************************************************************/ class ConvertCommand : Command { private { string m_format; bool m_stdout; } this() { this.name = "convert"; this.argumentsPattern = ""; this.description = "Converts the file format of the package recipe."; this.helpText = [ "This command will convert between JSON and SDLang formatted package recipe files.", "", "Warning: Beware that any formatting and comments within the package recipe will get lost in the conversion process." ]; } override void prepare(scope CommandArgs args) { args.getopt("f|format", &m_format, ["Specifies the target package recipe format. Possible values:", " json, sdl"]); args.getopt("s|stdout", &m_stdout, ["Outputs the converted package recipe to stdout instead of writing to disk."]); } override int execute(Dub dub, string[] free_args, string[] app_args) { enforceUsage(app_args.length == 0, "Unexpected application arguments."); enforceUsage(free_args.length == 0, "Unexpected arguments: "~free_args.join(" ")); enforceUsage(m_format.length > 0, "Missing target format file extension (--format=...)."); if (!loadCwdPackage(dub, true)) return 1; dub.convertRecipe(m_format, m_stdout); return 0; } } /******************************************************************************/ /* HELP */ /******************************************************************************/ private { enum shortArgColumn = 2; enum longArgColumn = 6; enum descColumn = 24; enum lineWidth = 80 - 1; } private void showHelp(in CommandGroup[] commands, CommandArgs common_args) { writeln( `USAGE: dub [--version] [] [] [-- []] Manages the DUB project in the current directory. If the command is omitted, DUB will default to "run". When running an application, "--" can be used to separate DUB options from options passed to the application. Run "dub --help" to get help for a specific command. You can use the "http_proxy" environment variable to configure a proxy server to be used for fetching packages. Available commands ==================`); foreach (grp; commands) { writeln(); writeWS(shortArgColumn); writeln(grp.caption); writeWS(shortArgColumn); writerep!'-'(grp.caption.length); writeln(); foreach (cmd; grp.commands) { if (cmd.hidden) continue; writeWS(shortArgColumn); writef("%s %s", cmd.name, cmd.argumentsPattern); auto chars_output = cmd.name.length + cmd.argumentsPattern.length + shortArgColumn + 1; if (chars_output < descColumn) { writeWS(descColumn - chars_output); } else { writeln(); writeWS(descColumn); } writeWrapped(cmd.description, descColumn, descColumn); } } writeln(); writeln(); writeln(`Common options`); writeln(`==============`); writeln(); writeOptions(common_args); writeln(); showVersion(); } private void showVersion() { writefln("DUB version %s, built on %s", getDUBVersion(), __DATE__); } private void showCommandHelp(Command cmd, CommandArgs args, CommandArgs common_args) { writefln(`USAGE: dub %s %s []%s`, cmd.name, cmd.argumentsPattern, cmd.acceptsAppArgs ? " [-- ]": null); writeln(); foreach (ln; cmd.helpText) ln.writeWrapped(); if (args.recognizedArgs.length) { writeln(); writeln(); writeln("Command specific options"); writeln("========================"); writeln(); writeOptions(args); } writeln(); writeln(); writeln("Common options"); writeln("=============="); writeln(); writeOptions(common_args); writeln(); writefln("DUB version %s, built on %s", getDUBVersion(), __DATE__); } private void writeOptions(CommandArgs args) { foreach (arg; args.recognizedArgs) { auto names = arg.names.split("|"); assert(names.length == 1 || names.length == 2); string sarg = names[0].length == 1 ? names[0] : null; string larg = names[0].length > 1 ? names[0] : names.length > 1 ? names[1] : null; if (sarg !is null) { writeWS(shortArgColumn); writef("-%s", sarg); writeWS(longArgColumn - shortArgColumn - 2); } else writeWS(longArgColumn); size_t col = longArgColumn; if (larg !is null) { if (arg.defaultValue.peek!bool) { writef("--%s", larg); col += larg.length + 2; } else { writef("--%s=VALUE", larg); col += larg.length + 8; } } if (col < descColumn) { writeWS(descColumn - col); } else { writeln(); writeWS(descColumn); } foreach (i, ln; arg.helpText) { if (i > 0) writeWS(descColumn); ln.writeWrapped(descColumn, descColumn); } } } private void writeWrapped(string string, size_t indent = 0, size_t first_line_pos = 0) { // handle pre-indented strings and bullet lists size_t first_line_indent = 0; while (string.startsWith(" ")) { string = string[1 .. $]; indent++; first_line_indent++; } if (string.startsWith("- ")) indent += 2; auto wrapped = string.wrap(lineWidth, getRepString!' '(first_line_pos+first_line_indent), getRepString!' '(indent)); wrapped = wrapped[first_line_pos .. $]; foreach (ln; wrapped.splitLines()) writeln(ln); } private void writeWS(size_t num) { writerep!' '(num); } private void writerep(char ch)(size_t num) { write(getRepString!ch(num)); } private string getRepString(char ch)(size_t len) { static string buf; if (len > buf.length) buf ~= [ch].replicate(len-buf.length); return buf[0 .. len]; } /*** */ private void enforceUsage(bool cond, string text) { if (!cond) throw new UsageException(text); } private class UsageException : Exception { this(string message, string file = __FILE__, int line = __LINE__, Throwable next = null) { super(message, file, line, next); } } private void warnRenamed(string prev, string curr) { logWarn("The '%s' Command was renamed to '%s'. Please update your scripts.", prev, curr); } private bool addDependency(Dub dub, ref PackageRecipe recipe, string depspec) { Dependency dep; const parts = splitPackageName(depspec); const depname = parts.name; if (parts.version_) dep = Dependency(parts.version_); else { try { const ver = dub.getLatestVersion(depname); dep = ver.isBranch ? Dependency(ver) : Dependency("~>" ~ ver.toString()); } catch (Exception e) { logError("Could not find package '%s'.", depname); logDebug("Full error: %s", e.toString().sanitize); return false; } } recipe.buildSettings.dependencies[depname] = dep; logInfo("Adding dependency %s %s", depname, dep.versionSpec); return true; } private struct PackageAndVersion { string name; string version_; } /* Split = and @ into `name` and `version_`. */ private PackageAndVersion splitPackageName(string packageName) { // split @ auto parts = packageName.findSplit("@"); if (parts[1].empty) { // split = parts = packageName.findSplit("="); } PackageAndVersion p; p.name = parts[0]; if (!parts[1].empty) p.version_ = parts[2]; return p; } unittest { // https://github.com/dlang/dub/issues/1681 assert(splitPackageName("") == PackageAndVersion("", null)); assert(splitPackageName("foo=1.0.1") == PackageAndVersion("foo", "1.0.1")); assert(splitPackageName("foo@1.0.1") == PackageAndVersion("foo", "1.0.1")); assert(splitPackageName("foo@==1.0.1") == PackageAndVersion("foo", "==1.0.1")); assert(splitPackageName("foo@>=1.0.1") == PackageAndVersion("foo", ">=1.0.1")); assert(splitPackageName("foo@~>1.0.1") == PackageAndVersion("foo", "~>1.0.1")); assert(splitPackageName("foo@<1.0.1") == PackageAndVersion("foo", "<1.0.1")); } dub-1.19.0/source/dub/compilers/000077500000000000000000000000001360435400500164235ustar00rootroot00000000000000dub-1.19.0/source/dub/compilers/buildsettings.d000066400000000000000000000324121360435400500214520ustar00rootroot00000000000000/** Build settings definitions. Copyright: © 2013-2014 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.compilers.buildsettings; import dub.internal.vibecompat.inet.path; import std.array : array; import std.algorithm : filter, any; import std.path : globMatch; import std.typecons : BitFlags; /// BuildPlatform specific settings, like needed libraries or additional /// include paths. struct BuildSettings { import dub.internal.vibecompat.data.serialization : byName; TargetType targetType; string targetPath; string targetName; string workingDirectory; string mainSourceFile; string[] dflags; string[] lflags; string[] libs; string[] linkerFiles; string[] sourceFiles; string[] copyFiles; string[] extraDependencyFiles; string[] versions; string[] debugVersions; string[] versionFilters; string[] debugVersionFilters; string[] importPaths; string[] stringImportPaths; string[] importFiles; string[] stringImportFiles; string[] preGenerateCommands; string[] postGenerateCommands; string[] preBuildCommands; string[] postBuildCommands; string[] preRunCommands; string[] postRunCommands; @byName BuildRequirements requirements; @byName BuildOptions options; BuildSettings dup() const { BuildSettings ret; foreach (m; __traits(allMembers, BuildSettings)) { static if (is(typeof(__traits(getMember, ret, m) = __traits(getMember, this, m).dup))) __traits(getMember, ret, m) = __traits(getMember, this, m).dup; else static if (is(typeof(__traits(getMember, ret, m) = __traits(getMember, this, m)))) __traits(getMember, ret, m) = __traits(getMember, this, m); } assert(ret.targetType == targetType); assert(ret.targetName == targetName); assert(ret.importPaths == importPaths); return ret; } void add(in BuildSettings bs) { addDFlags(bs.dflags); addLFlags(bs.lflags); addLibs(bs.libs); addLinkerFiles(bs.linkerFiles); addSourceFiles(bs.sourceFiles); addCopyFiles(bs.copyFiles); addExtraDependencyFiles(bs.extraDependencyFiles); addVersions(bs.versions); addDebugVersions(bs.debugVersions); addVersionFilters(bs.versionFilters); addDebugVersionFilters(bs.debugVersionFilters); addImportPaths(bs.importPaths); addStringImportPaths(bs.stringImportPaths); addImportFiles(bs.importFiles); addStringImportFiles(bs.stringImportFiles); addPreGenerateCommands(bs.preGenerateCommands); addPostGenerateCommands(bs.postGenerateCommands); addPreBuildCommands(bs.preBuildCommands); addPostBuildCommands(bs.postBuildCommands); addPreRunCommands(bs.preRunCommands); addPostRunCommands(bs.postRunCommands); } void addDFlags(in string[] value...) { dflags ~= value; } void prependDFlags(in string[] value...) { prepend(dflags, value); } void removeDFlags(in string[] value...) { remove(dflags, value); } void addLFlags(in string[] value...) { lflags ~= value; } void addLibs(in string[] value...) { add(libs, value); } void addLinkerFiles(in string[] value...) { add(linkerFiles, value); } void addSourceFiles(in string[] value...) { add(sourceFiles, value); } void prependSourceFiles(in string[] value...) { prepend(sourceFiles, value); } void removeSourceFiles(in string[] value...) { removePaths(sourceFiles, value); } void addCopyFiles(in string[] value...) { add(copyFiles, value); } void addExtraDependencyFiles(in string[] value...) { add(extraDependencyFiles, value); } void addVersions(in string[] value...) { add(versions, value); } void addDebugVersions(in string[] value...) { add(debugVersions, value); } void addVersionFilters(in string[] value...) { add(versionFilters, value); } void addDebugVersionFilters(in string[] value...) { add(debugVersionFilters, value); } void addImportPaths(in string[] value...) { add(importPaths, value); } void addStringImportPaths(in string[] value...) { add(stringImportPaths, value); } void prependStringImportPaths(in string[] value...) { prepend(stringImportPaths, value); } void addImportFiles(in string[] value...) { add(importFiles, value); } void addStringImportFiles(in string[] value...) { addSI(stringImportFiles, value); } void addPreGenerateCommands(in string[] value...) { add(preGenerateCommands, value, false); } void addPostGenerateCommands(in string[] value...) { add(postGenerateCommands, value, false); } void addPreBuildCommands(in string[] value...) { add(preBuildCommands, value, false); } void addPostBuildCommands(in string[] value...) { add(postBuildCommands, value, false); } void addPreRunCommands(in string[] value...) { add(preRunCommands, value, false); } void addPostRunCommands(in string[] value...) { add(postRunCommands, value, false); } void addRequirements(in BuildRequirement[] value...) { foreach (v; value) this.requirements |= v; } void addRequirements(in BuildRequirements value) { this.requirements |= value; } void addOptions(in BuildOption[] value...) { foreach (v; value) this.options |= v; } void addOptions(in BuildOptions value) { this.options |= value; } void removeOptions(in BuildOption[] value...) { foreach (v; value) this.options &= ~v; } void removeOptions(in BuildOptions value) { this.options &= ~value; } private: static auto filterDuplicates(T)(ref string[] arr, in T vals, bool noDuplicates = true) { return noDuplicates ? vals.filter!(filtered => !arr.any!(item => item == filtered)).array : vals; } // Append vals to arr without adding duplicates. static void add(ref string[] arr, in string[] vals, bool noDuplicates = true) { arr ~= filterDuplicates(arr, vals, noDuplicates); } unittest { auto ary = ["-dip1000", "-vgc"]; BuildSettings.add(ary, ["-dip1000", "-vgc"]); assert(ary == ["-dip1000", "-vgc"]); BuildSettings.add(ary, ["-dip1001", "-vgc"], false); assert(ary == ["-dip1000", "-vgc", "-dip1001", "-vgc"]); } // Prepend arr by vals without adding duplicates. static void prepend(ref string[] arr, in string[] vals, bool noDuplicates = true) { arr = filterDuplicates(arr, vals, noDuplicates) ~ arr; } unittest { auto ary = ["-dip1000", "-vgc"]; BuildSettings.prepend(ary, ["-dip1000", "-vgc"]); assert(ary == ["-dip1000", "-vgc"]); BuildSettings.prepend(ary, ["-dip1001", "-vgc"], false); assert(ary == ["-dip1001", "-vgc", "-dip1000", "-vgc"]); } // add string import files (avoids file name duplicates in addition to path duplicates) static void addSI(ref string[] arr, in string[] vals) { bool[string] existing; foreach (v; arr) existing[NativePath(v).head.name] = true; foreach (v; vals) { auto s = NativePath(v).head.name; if (s !in existing) { existing[s] = true; arr ~= v; } } } unittest { auto ary = ["path/foo.txt"]; BuildSettings.addSI(ary, ["path2/foo2.txt"]); assert(ary == ["path/foo.txt", "path2/foo2.txt"]); BuildSettings.addSI(ary, ["path2/foo.txt"]); // no duplicate basenames assert(ary == ["path/foo.txt", "path2/foo2.txt"]); } static bool pathMatch(string path, string pattern) { import std.functional : memoize; alias nativePath = memoize!((string stringPath) => NativePath(stringPath)); return nativePath(path) == nativePath(pattern) || globMatch(path, pattern); } static void removeValuesFromArray(alias Match)(ref string[] arr, in string[] vals) { bool matches(string s) { return vals.any!(item => Match(s, item)); } arr = arr.filter!(s => !matches(s)).array; } static void removePaths(ref string[] arr, in string[] vals) { removeValuesFromArray!(pathMatch)(arr, vals); } unittest { auto ary = ["path1", "root/path1", "root/path2", "root2/path1"]; BuildSettings.removePaths(ary, ["path1"]); assert(ary == ["root/path1", "root/path2", "root2/path1"]); BuildSettings.removePaths(ary, ["*/path1"]); assert(ary == ["root/path2"]); BuildSettings.removePaths(ary, ["foo", "bar", "root/path2"]); assert(ary == []); } static void remove(ref string[] arr, in string[] vals) { removeValuesFromArray!((a, b) => a == b)(arr, vals); } unittest { import std.string : join; auto ary = ["path1", "root/path1", "root/path2", "root2/path1"]; BuildSettings.remove(ary, ["path1"]); assert(ary == ["root/path1", "root/path2", "root2/path1"]); BuildSettings.remove(ary, ["root/path*"]); assert(ary == ["root/path1", "root/path2", "root2/path1"]); BuildSettings.removePaths(ary, ["foo", "root/path2", "bar", "root2/path1"]); assert(ary == ["root/path1"]); BuildSettings.remove(ary, ["root/path1", "foo"]); assert(ary == []); } } enum BuildSetting { dflags = 1<<0, lflags = 1<<1, libs = 1<<2, sourceFiles = 1<<3, copyFiles = 1<<4, versions = 1<<5, debugVersions = 1<<6, importPaths = 1<<7, stringImportPaths = 1<<8, options = 1<<9, none = 0, commandLine = dflags|copyFiles, commandLineSeparate = commandLine|lflags, all = dflags|lflags|libs|sourceFiles|copyFiles|versions|debugVersions|importPaths|stringImportPaths|options, noOptions = all & ~options } enum TargetType { autodetect, none, executable, library, sourceLibrary, dynamicLibrary, staticLibrary, object } enum BuildRequirement { none = 0, /// No special requirements allowWarnings = 1<<0, /// Warnings do not abort compilation silenceWarnings = 1<<1, /// Don't show warnings disallowDeprecations = 1<<2, /// Using deprecated features aborts compilation silenceDeprecations = 1<<3, /// Don't show deprecation warnings disallowInlining = 1<<4, /// Avoid function inlining, even in release builds disallowOptimization = 1<<5, /// Avoid optimizations, even in release builds requireBoundsCheck = 1<<6, /// Always perform bounds checks requireContracts = 1<<7, /// Leave assertions and contracts enabled in release builds relaxProperties = 1<<8, /// DEPRECATED: Do not enforce strict property handling (-property) noDefaultFlags = 1<<9, /// Do not issue any of the default build flags (e.g. -debug, -w, -property etc.) - use only for development purposes } struct BuildRequirements { import dub.internal.vibecompat.data.serialization : ignore; @ignore BitFlags!BuildRequirement values; this(BuildRequirement req) { values = req; } alias values this; } enum BuildOption { none = 0, /// Use compiler defaults debugMode = 1<<0, /// Compile in debug mode (enables contracts, -debug) releaseMode = 1<<1, /// Compile in release mode (disables assertions and bounds checks, -release) coverage = 1<<2, /// Enable code coverage analysis (-cov) debugInfo = 1<<3, /// Enable symbolic debug information (-g) debugInfoC = 1<<4, /// Enable symbolic debug information in C compatible form (-gc) alwaysStackFrame = 1<<5, /// Always generate a stack frame (-gs) stackStomping = 1<<6, /// Perform stack stomping (-gx) inline = 1<<7, /// Perform function inlining (-inline) noBoundsCheck = 1<<8, /// Disable all bounds checking (-noboundscheck) optimize = 1<<9, /// Enable optimizations (-O) profile = 1<<10, /// Emit profiling code (-profile) unittests = 1<<11, /// Compile unit tests (-unittest) verbose = 1<<12, /// Verbose compiler output (-v) ignoreUnknownPragmas = 1<<13, /// Ignores unknown pragmas during compilation (-ignore) syntaxOnly = 1<<14, /// Don't generate object files (-o-) warnings = 1<<15, /// Enable warnings (-wi) warningsAsErrors = 1<<16, /// Treat warnings as errors (-w) ignoreDeprecations = 1<<17, /// Do not warn about using deprecated features (-d) deprecationWarnings = 1<<18, /// Warn about using deprecated features (-dw) deprecationErrors = 1<<19, /// Stop compilation upon usage of deprecated features (-de) property = 1<<20, /// DEPRECATED: Enforce property syntax (-property) profileGC = 1<<21, /// Profile runtime allocations pic = 1<<22, /// Generate position independent code betterC = 1<<23, /// Compile in betterC mode (-betterC) // for internal usage _docs = 1<<24, // Write ddoc to docs _ddox = 1<<25 // Compile docs.json } struct BuildOptions { import dub.internal.vibecompat.data.serialization : ignore; @ignore BitFlags!BuildOption values; this(BuildOption opt) { values = opt; } this(BitFlags!BuildOption v) { values = v; } alias values this; } /** All build options that will be inherited upwards in the dependency graph Build options in this category fulfill one of the following properties: $(UL $(LI The option affects the semantics of the generated code) $(LI The option affects if a certain piece of code is valid or not) $(LI The option enabled meta information in dependent projects that are useful for the dependee (e.g. debug information)) ) */ enum BuildOptions inheritedBuildOptions = BuildOption.debugMode | BuildOption.releaseMode | BuildOption.coverage | BuildOption.debugInfo | BuildOption.debugInfoC | BuildOption.alwaysStackFrame | BuildOption.stackStomping | BuildOption.inline | BuildOption.noBoundsCheck | BuildOption.profile | BuildOption.ignoreUnknownPragmas | BuildOption.syntaxOnly | BuildOption.warnings | BuildOption.warningsAsErrors | BuildOption.ignoreDeprecations | BuildOption.deprecationWarnings | BuildOption.deprecationErrors | BuildOption.property | BuildOption.profileGC | BuildOption.pic; dub-1.19.0/source/dub/compilers/compiler.d000066400000000000000000000140011360435400500203760ustar00rootroot00000000000000/** Compiler settings and abstraction. Copyright: © 2013-2016 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.compilers.compiler; public import dub.compilers.buildsettings; public import dub.dependency : Dependency; public import dub.platform : BuildPlatform, matchesSpecification; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; import dub.recipe.packagerecipe : ToolchainRequirements; import std.algorithm; import std.array; import std.conv; import std.exception; import std.process; import std.typecons : Flag; /** Returns a compiler handler for a given binary name. The name will be compared against the canonical name of each registered compiler handler. If no match is found, the sub strings "dmd", "gdc" and "ldc", in this order, will be searched within the name. If this doesn't yield a match either, an exception will be thrown. */ Compiler getCompiler(string name) { foreach (c; s_compilers) if (c.name == name) return c; // try to match names like gdmd or gdc-2.61 if (name.canFind("dmd")) return getCompiler("dmd"); if (name.canFind("gdc")) return getCompiler("gdc"); if (name.canFind("ldc")) return getCompiler("ldc"); throw new Exception("Unknown compiler: "~name); } /** Registers a new compiler handler. Note that by default `DMDCompiler`, `GDCCompiler` and `LDCCompiler` are already registered at startup. */ void registerCompiler(Compiler c) { s_compilers ~= c; } interface Compiler { /// Returns the canonical name of the compiler (e.g. "dmd"). @property string name() const; /** Determines the build platform properties given a set of build settings. This will invoke the compiler to build a platform probe file, which determines the target build platform's properties during compile-time. See_Also: `dub.compilers.utils.generatePlatformProbeFile` */ BuildPlatform determinePlatform(ref BuildSettings settings, string compiler_binary, string arch_override = null); /// Replaces high level fields with low level fields and converts /// dmd flags to compiler-specific flags void prepareBuildSettings(ref BuildSettings settings, in ref BuildPlatform platform, BuildSetting supported_fields = BuildSetting.all) const; /// Removes any dflags that match one of the BuildOptions values and populates the BuildSettings.options field. void extractBuildOptions(ref BuildSettings settings) const; /// Computes the full file name of the generated binary. string getTargetFileName(in BuildSettings settings, in BuildPlatform platform) const; /// Adds the appropriate flag to set a target path void setTarget(ref BuildSettings settings, in BuildPlatform platform, string targetPath = null) const; /// Invokes the compiler using the given flags void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback); /// Invokes the underlying linker directly void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback); /// Convert linker flags to compiler format string[] lflagsToDFlags(in string[] lflags) const; /// Determines compiler version string determineVersion(string compiler_binary, string verboseOutput); /** Runs a tool and provides common boilerplate code. This method should be used by `Compiler` implementations to invoke the compiler or linker binary. */ protected final void invokeTool(string[] args, void delegate(int, string) output_callback) { import std.string; int status; if (output_callback) { auto result = executeShell(escapeShellCommand(args)); output_callback(result.status, result.output); status = result.status; } else { auto compiler_pid = spawnShell(escapeShellCommand(args)); status = compiler_pid.wait(); } version (Posix) if (status == -9) { throw new Exception(format("%s failed with exit code %s. This may indicate that the process has run out of memory.", args[0], status)); } enforce(status == 0, format("%s failed with exit code %s.", args[0], status)); } /** Compiles platform probe file with the specified compiler and parses its output. Params: compiler_binary = binary to invoke compiler with args = arguments for the probe compilation arch_override = special handler for x86_mscoff */ protected final BuildPlatform probePlatform(string compiler_binary, string[] args, string arch_override) { import dub.compilers.utils : generatePlatformProbeFile, readPlatformJsonProbe; import std.string : format, strip; auto fil = generatePlatformProbeFile(); auto result = executeShell(escapeShellCommand(compiler_binary ~ args ~ fil.toNativeString())); enforce(result.status == 0, format("Failed to invoke the compiler %s to determine the build platform: %s", compiler_binary, result.output)); auto build_platform = readPlatformJsonProbe(result.output); build_platform.compilerBinary = compiler_binary; auto ver = determineVersion(compiler_binary, result.output) .strip; if (ver.empty) { logWarn(`Could not probe the compiler version for "%s". ` ~ `Toolchain requirements might be ineffective`, build_platform.compiler); } else { build_platform.compilerVersion = ver; } // Hack: see #1059 // When compiling with --arch=x86_mscoff build_platform.architecture is equal to ["x86"] and canFind below is false. // This hack prevents unnesessary warning 'Failed to apply the selected architecture x86_mscoff. Got ["x86"]'. // And also makes "x86_mscoff" available as a platform specifier in the package recipe if (arch_override == "x86_mscoff") build_platform.architecture ~= arch_override; if (arch_override.length && !build_platform.architecture.canFind(arch_override)) { logWarn(`Failed to apply the selected architecture %s. Got %s.`, arch_override, build_platform.architecture); } return build_platform; } } private { Compiler[] s_compilers; } dub-1.19.0/source/dub/compilers/dmd.d000066400000000000000000000244401360435400500173400ustar00rootroot00000000000000/** DMD compiler support. Copyright: © 2013-2013 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.compilers.dmd; import dub.compilers.compiler; import dub.compilers.utils; import dub.internal.utils; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import dub.recipe.packagerecipe : ToolchainRequirements; import std.algorithm; import std.array; import std.conv; import std.exception; import std.file; import std.process; import std.typecons; // Determines whether the specified process is running under WOW64 or an Intel64 of x64 processor. version (Windows) private Nullable!bool isWow64() { // See also: https://docs.microsoft.com/de-de/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getnativesysteminfo import core.sys.windows.windows : GetNativeSystemInfo, SYSTEM_INFO, PROCESSOR_ARCHITECTURE_AMD64; static Nullable!bool result; // A process's architecture won't change over while the process is in memory // Return the cached result if (!result.isNull) return result; SYSTEM_INFO systemInfo; GetNativeSystemInfo(&systemInfo); result = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; return result; } class DMDCompiler : Compiler { private static immutable s_options = [ tuple(BuildOption.debugMode, ["-debug"]), tuple(BuildOption.releaseMode, ["-release"]), tuple(BuildOption.coverage, ["-cov"]), tuple(BuildOption.debugInfo, ["-g"]), tuple(BuildOption.debugInfoC, ["-g"]), tuple(BuildOption.alwaysStackFrame, ["-gs"]), tuple(BuildOption.stackStomping, ["-gx"]), tuple(BuildOption.inline, ["-inline"]), tuple(BuildOption.noBoundsCheck, ["-noboundscheck"]), tuple(BuildOption.optimize, ["-O"]), tuple(BuildOption.profile, ["-profile"]), tuple(BuildOption.unittests, ["-unittest"]), tuple(BuildOption.verbose, ["-v"]), tuple(BuildOption.ignoreUnknownPragmas, ["-ignore"]), tuple(BuildOption.syntaxOnly, ["-o-"]), tuple(BuildOption.warnings, ["-wi"]), tuple(BuildOption.warningsAsErrors, ["-w"]), tuple(BuildOption.ignoreDeprecations, ["-d"]), tuple(BuildOption.deprecationWarnings, ["-dw"]), tuple(BuildOption.deprecationErrors, ["-de"]), tuple(BuildOption.property, ["-property"]), tuple(BuildOption.profileGC, ["-profile=gc"]), tuple(BuildOption.betterC, ["-betterC"]), tuple(BuildOption._docs, ["-Dddocs"]), tuple(BuildOption._ddox, ["-Xfdocs.json", "-Df__dummy.html"]), ]; @property string name() const { return "dmd"; } enum dmdVersionRe = `^version\s+v?(\d+\.\d+\.\d+[A-Za-z0-9.+-]*)`; unittest { import std.regex : matchFirst, regex; auto probe = ` binary dmd version v2.082.0 config /etc/dmd.conf `; auto re = regex(dmdVersionRe, "m"); auto c = matchFirst(probe, re); assert(c && c.length > 1 && c[1] == "2.082.0"); } unittest { import std.regex : matchFirst, regex; auto probe = ` binary dmd version v2.084.0-beta.1 config /etc/dmd.conf `; auto re = regex(dmdVersionRe, "m"); auto c = matchFirst(probe, re); assert(c && c.length > 1 && c[1] == "2.084.0-beta.1"); } string determineVersion(string compiler_binary, string verboseOutput) { import std.regex : matchFirst, regex; auto ver = matchFirst(verboseOutput, regex(dmdVersionRe, "m")); return ver && ver.length > 1 ? ver[1] : null; } BuildPlatform determinePlatform(ref BuildSettings settings, string compiler_binary, string arch_override) { string[] arch_flags; switch (arch_override) { default: throw new Exception("Unsupported architecture: "~arch_override); case "": // Don't use Optlink by default on Windows version (Windows) { const is64bit = isWow64(); if (!is64bit.isNull) arch_flags = [is64bit.get ? "-m64" : "-m32mscoff"]; } break; case "x86": arch_flags = ["-m32"]; break; case "x86_64": arch_flags = ["-m64"]; break; case "x86_mscoff": arch_flags = ["-m32mscoff"]; break; } settings.addDFlags(arch_flags); return probePlatform( compiler_binary, arch_flags ~ ["-quiet", "-c", "-o-", "-v"], arch_override ); } void prepareBuildSettings(ref BuildSettings settings, in ref BuildPlatform platform, BuildSetting fields = BuildSetting.all) const { enforceBuildRequirements(settings); if (!(fields & BuildSetting.options)) { foreach (t; s_options) if (settings.options & t[0]) settings.addDFlags(t[1]); } if (!(fields & BuildSetting.versions)) { settings.addDFlags(settings.versions.map!(s => "-version="~s)().array()); settings.versions = null; } if (!(fields & BuildSetting.debugVersions)) { settings.addDFlags(settings.debugVersions.map!(s => "-debug="~s)().array()); settings.debugVersions = null; } if (!(fields & BuildSetting.importPaths)) { settings.addDFlags(settings.importPaths.map!(s => "-I"~s)().array()); settings.importPaths = null; } if (!(fields & BuildSetting.stringImportPaths)) { settings.addDFlags(settings.stringImportPaths.map!(s => "-J"~s)().array()); settings.stringImportPaths = null; } if (!(fields & BuildSetting.libs)) { resolveLibs(settings, platform); if (platform.platform.canFind("windows")) settings.addSourceFiles(settings.libs.map!(l => l~".lib")().array()); else settings.addLFlags(settings.libs.map!(l => "-l"~l)().array()); } if (!(fields & BuildSetting.sourceFiles)) { settings.addDFlags(settings.sourceFiles); settings.sourceFiles = null; } if (!(fields & BuildSetting.lflags)) { settings.addDFlags(lflagsToDFlags(settings.lflags)); settings.lflags = null; } if (platform.platform.canFind("posix") && (settings.options & BuildOption.pic)) settings.addDFlags("-fPIC"); assert(fields & BuildSetting.dflags); assert(fields & BuildSetting.copyFiles); } void extractBuildOptions(ref BuildSettings settings) const { Appender!(string[]) newflags; next_flag: foreach (f; settings.dflags) { foreach (t; s_options) if (t[1].canFind(f)) { settings.options |= t[0]; continue next_flag; } if (f.startsWith("-version=")) settings.addVersions(f[9 .. $]); else if (f.startsWith("-debug=")) settings.addDebugVersions(f[7 .. $]); else newflags ~= f; } settings.dflags = newflags.data; } string getTargetFileName(in BuildSettings settings, in BuildPlatform platform) const { import std.conv: text; assert(settings.targetName.length > 0, "No target name set."); final switch (settings.targetType) { case TargetType.autodetect: assert(false, text("Configurations must have a concrete target type, ", settings.targetName, " has ", settings.targetType)); case TargetType.none: return null; case TargetType.sourceLibrary: return null; case TargetType.executable: if (platform.platform.canFind("windows")) return settings.targetName ~ ".exe"; else return settings.targetName.idup; case TargetType.library: case TargetType.staticLibrary: if (platform.platform.canFind("windows")) return settings.targetName ~ ".lib"; else return "lib" ~ settings.targetName ~ ".a"; case TargetType.dynamicLibrary: if (platform.platform.canFind("windows")) return settings.targetName ~ ".dll"; else if (platform.platform.canFind("osx")) return "lib" ~ settings.targetName ~ ".dylib"; else return "lib" ~ settings.targetName ~ ".so"; case TargetType.object: if (platform.platform.canFind("windows")) return settings.targetName ~ ".obj"; else return settings.targetName ~ ".o"; } } void setTarget(ref BuildSettings settings, in BuildPlatform platform, string tpath = null) const { final switch (settings.targetType) { case TargetType.autodetect: assert(false, "Invalid target type: autodetect"); case TargetType.none: assert(false, "Invalid target type: none"); case TargetType.sourceLibrary: assert(false, "Invalid target type: sourceLibrary"); case TargetType.executable: break; case TargetType.library: case TargetType.staticLibrary: settings.addDFlags("-lib"); break; case TargetType.dynamicLibrary: if (platform.compiler != "dmd" || platform.platform.canFind("windows") || platform.platform.canFind("osx")) settings.addDFlags("-shared"); else settings.prependDFlags("-shared", "-defaultlib=libphobos2.so"); break; case TargetType.object: settings.addDFlags("-c"); break; } if (tpath is null) tpath = (NativePath(settings.targetPath) ~ getTargetFileName(settings, platform)).toNativeString(); settings.addDFlags("-of"~tpath); } void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback) { auto res_file = getTempFile("dub-build", ".rsp"); const(string)[] args = settings.dflags; if (platform.frontendVersion >= 2066) args ~= "-vcolumns"; std.file.write(res_file.toNativeString(), escapeArgs(args).join("\n")); logDiagnostic("%s %s", platform.compilerBinary, escapeArgs(args).join(" ")); invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback); } void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback) { import std.string; auto tpath = NativePath(settings.targetPath) ~ getTargetFileName(settings, platform); auto args = ["-of"~tpath.toNativeString()]; args ~= objects; args ~= settings.sourceFiles; if (platform.platform.canFind("linux")) args ~= "-L--no-as-needed"; // avoids linker errors due to libraries being specified in the wrong order by DMD args ~= lflagsToDFlags(settings.lflags); args ~= settings.dflags.filter!(f => isLinkerDFlag(f)).array; auto res_file = getTempFile("dub-build", ".lnk"); std.file.write(res_file.toNativeString(), escapeArgs(args).join("\n")); logDiagnostic("%s %s", platform.compilerBinary, escapeArgs(args).join(" ")); invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback); } string[] lflagsToDFlags(in string[] lflags) const { return map!(f => "-L"~f)(lflags.filter!(f => f != "")()).array(); } private auto escapeArgs(in string[] args) { return args.map!(s => s.canFind(' ') ? "\""~s~"\"" : s); } private static bool isLinkerDFlag(string arg) { switch (arg) { default: if (arg.startsWith("-defaultlib=")) return true; return false; case "-g", "-gc", "-m32", "-m64", "-shared", "-lib", "-m32mscoff": return true; } } } dub-1.19.0/source/dub/compilers/gdc.d000066400000000000000000000211121360435400500173220ustar00rootroot00000000000000/** GDC compiler support. Copyright: © 2013-2013 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.compilers.gdc; import dub.compilers.compiler; import dub.compilers.utils; import dub.internal.utils; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import dub.recipe.packagerecipe : ToolchainRequirements; import std.algorithm; import std.array; import std.conv; import std.exception; import std.file; import std.process; import std.typecons; class GDCCompiler : Compiler { private static immutable s_options = [ tuple(BuildOption.debugMode, ["-fdebug"]), tuple(BuildOption.releaseMode, ["-frelease"]), tuple(BuildOption.coverage, ["-fprofile-arcs", "-ftest-coverage"]), tuple(BuildOption.debugInfo, ["-g"]), tuple(BuildOption.debugInfoC, ["-g", "-fdebug-c"]), //tuple(BuildOption.alwaysStackFrame, ["-X"]), //tuple(BuildOption.stackStomping, ["-X"]), tuple(BuildOption.inline, ["-finline-functions"]), tuple(BuildOption.noBoundsCheck, ["-fno-bounds-check"]), tuple(BuildOption.optimize, ["-O3"]), tuple(BuildOption.profile, ["-pg"]), tuple(BuildOption.unittests, ["-funittest"]), tuple(BuildOption.verbose, ["-fd-verbose"]), tuple(BuildOption.ignoreUnknownPragmas, ["-fignore-unknown-pragmas"]), tuple(BuildOption.syntaxOnly, ["-fsyntax-only"]), tuple(BuildOption.warnings, ["-Wall"]), tuple(BuildOption.warningsAsErrors, ["-Werror", "-Wall"]), tuple(BuildOption.ignoreDeprecations, ["-Wno-deprecated"]), tuple(BuildOption.deprecationWarnings, ["-Wdeprecated"]), tuple(BuildOption.deprecationErrors, ["-Werror", "-Wdeprecated"]), tuple(BuildOption.property, ["-fproperty"]), //tuple(BuildOption.profileGC, ["-?"]), tuple(BuildOption._docs, ["-fdoc-dir=docs"]), tuple(BuildOption._ddox, ["-fXf=docs.json", "-fdoc-file=__dummy.html"]), ]; @property string name() const { return "gdc"; } string determineVersion(string compiler_binary, string verboseOutput) { const result = execute([ compiler_binary, "-dumpfullversion", "-dumpversion" ]); return result.status == 0 ? result.output : null; } BuildPlatform determinePlatform(ref BuildSettings settings, string compiler_binary, string arch_override) { string[] arch_flags; switch (arch_override) { default: throw new Exception("Unsupported architecture: "~arch_override); case "": break; case "arm": arch_flags = ["-marm"]; break; case "arm_thumb": arch_flags = ["-mthumb"]; break; case "x86": arch_flags = ["-m32"]; break; case "x86_64": arch_flags = ["-m64"]; break; } settings.addDFlags(arch_flags); return probePlatform( compiler_binary, arch_flags ~ ["-S", "-v"], arch_override ); } void prepareBuildSettings(ref BuildSettings settings, in ref BuildPlatform platform, BuildSetting fields = BuildSetting.all) const { enforceBuildRequirements(settings); if (!(fields & BuildSetting.options)) { foreach (t; s_options) if (settings.options & t[0]) settings.addDFlags(t[1]); } if (!(fields & BuildSetting.versions)) { settings.addDFlags(settings.versions.map!(s => "-fversion="~s)().array()); settings.versions = null; } if (!(fields & BuildSetting.debugVersions)) { settings.addDFlags(settings.debugVersions.map!(s => "-fdebug="~s)().array()); settings.debugVersions = null; } if (!(fields & BuildSetting.importPaths)) { settings.addDFlags(settings.importPaths.map!(s => "-I"~s)().array()); settings.importPaths = null; } if (!(fields & BuildSetting.stringImportPaths)) { settings.addDFlags(settings.stringImportPaths.map!(s => "-J"~s)().array()); settings.stringImportPaths = null; } if (!(fields & BuildSetting.sourceFiles)) { settings.addDFlags(settings.sourceFiles); settings.sourceFiles = null; } if (!(fields & BuildSetting.libs)) { resolveLibs(settings, platform); settings.addDFlags(settings.libs.map!(l => "-l"~l)().array()); } if (!(fields & BuildSetting.lflags)) { settings.addDFlags(lflagsToDFlags(settings.lflags)); settings.lflags = null; } if (settings.options & BuildOption.pic) settings.addDFlags("-fPIC"); assert(fields & BuildSetting.dflags); assert(fields & BuildSetting.copyFiles); } void extractBuildOptions(ref BuildSettings settings) const { Appender!(string[]) newflags; next_flag: foreach (f; settings.dflags) { foreach (t; s_options) if (t[1].canFind(f)) { settings.options |= t[0]; continue next_flag; } if (f.startsWith("-fversion=")) settings.addVersions(f[10 .. $]); else if (f.startsWith("-fdebug=")) settings.addDebugVersions(f[8 .. $]); else newflags ~= f; } settings.dflags = newflags.data; } string getTargetFileName(in BuildSettings settings, in BuildPlatform platform) const { assert(settings.targetName.length > 0, "No target name set."); final switch (settings.targetType) { case TargetType.autodetect: assert(false, "Configurations must have a concrete target type."); case TargetType.none: return null; case TargetType.sourceLibrary: return null; case TargetType.executable: if (platform.platform.canFind("windows")) return settings.targetName ~ ".exe"; else return settings.targetName.idup; case TargetType.library: case TargetType.staticLibrary: return "lib" ~ settings.targetName ~ ".a"; case TargetType.dynamicLibrary: if (platform.platform.canFind("windows")) return settings.targetName ~ ".dll"; else if (platform.platform.canFind("osx")) return "lib" ~ settings.targetName ~ ".dylib"; else return "lib" ~ settings.targetName ~ ".so"; case TargetType.object: if (platform.platform.canFind("windows")) return settings.targetName ~ ".obj"; else return settings.targetName ~ ".o"; } } void setTarget(ref BuildSettings settings, in BuildPlatform platform, string tpath = null) const { final switch (settings.targetType) { case TargetType.autodetect: assert(false, "Invalid target type: autodetect"); case TargetType.none: assert(false, "Invalid target type: none"); case TargetType.sourceLibrary: assert(false, "Invalid target type: sourceLibrary"); case TargetType.executable: break; case TargetType.library: case TargetType.staticLibrary: case TargetType.object: settings.addDFlags("-c"); break; case TargetType.dynamicLibrary: settings.addDFlags("-shared", "-fPIC"); break; } if (tpath is null) tpath = (NativePath(settings.targetPath) ~ getTargetFileName(settings, platform)).toNativeString(); settings.addDFlags("-o", tpath); } void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback) { auto res_file = getTempFile("dub-build", ".rsp"); std.file.write(res_file.toNativeString(), join(settings.dflags.map!(s => escape(s)), "\n")); logDiagnostic("%s %s", platform.compilerBinary, join(cast(string[])settings.dflags, " ")); invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback); } void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback) { import std.string; string[] args; // As the user is supposed to call setTarget prior to invoke, -o target is already set. if (settings.targetType == TargetType.staticLibrary || settings.targetType == TargetType.staticLibrary) { auto tpath = extractTarget(settings.dflags); assert(tpath !is null, "setTarget should be called before invoke"); args = [ "ar", "rcs", tpath ] ~ objects; } else { args = platform.compilerBinary ~ objects ~ settings.sourceFiles ~ settings.lflags ~ settings.dflags.filter!(f => isLinkageFlag(f)).array; if (platform.platform.canFind("linux")) args ~= "-L--no-as-needed"; // avoids linker errors due to libraries being specified in the wrong order } logDiagnostic("%s", args.join(" ")); invokeTool(args, output_callback); } string[] lflagsToDFlags(in string[] lflags) const { string[] dflags; foreach( f; lflags ) { if ( f == "") { continue; } dflags ~= "-Xlinker"; dflags ~= f; } return dflags; } } private string extractTarget(const string[] args) { auto i = args.countUntil("-o"); return i >= 0 ? args[i+1] : null; } private bool isLinkageFlag(string flag) { switch (flag) { case "-c": return false; default: return true; } } private string escape(string str) { auto ret = appender!string(); foreach (char ch; str) { switch (ch) { default: ret.put(ch); break; case '\\': ret.put(`\\`); break; case ' ': ret.put(`\ `); break; } } return ret.data; } dub-1.19.0/source/dub/compilers/ldc.d000066400000000000000000000226271360435400500173430ustar00rootroot00000000000000/** LDC compiler support. Copyright: © 2013-2013 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.compilers.ldc; import dub.compilers.compiler; import dub.compilers.utils; import dub.internal.utils; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import dub.recipe.packagerecipe : ToolchainRequirements; import std.algorithm; import std.array; import std.conv; import std.exception; import std.file; import std.process; import std.typecons; class LDCCompiler : Compiler { private static immutable s_options = [ tuple(BuildOption.debugMode, ["-d-debug"]), tuple(BuildOption.releaseMode, ["-release"]), tuple(BuildOption.coverage, ["-cov"]), tuple(BuildOption.debugInfo, ["-g"]), tuple(BuildOption.debugInfoC, ["-gc"]), tuple(BuildOption.alwaysStackFrame, ["-disable-fp-elim"]), //tuple(BuildOption.stackStomping, ["-?"]), tuple(BuildOption.inline, ["-enable-inlining", "-Hkeep-all-bodies"]), tuple(BuildOption.noBoundsCheck, ["-boundscheck=off"]), tuple(BuildOption.optimize, ["-O3"]), tuple(BuildOption.profile, ["-fdmd-trace-functions"]), tuple(BuildOption.unittests, ["-unittest"]), tuple(BuildOption.verbose, ["-v"]), tuple(BuildOption.ignoreUnknownPragmas, ["-ignore"]), tuple(BuildOption.syntaxOnly, ["-o-"]), tuple(BuildOption.warnings, ["-wi"]), tuple(BuildOption.warningsAsErrors, ["-w"]), tuple(BuildOption.ignoreDeprecations, ["-d"]), tuple(BuildOption.deprecationWarnings, ["-dw"]), tuple(BuildOption.deprecationErrors, ["-de"]), tuple(BuildOption.property, ["-property"]), //tuple(BuildOption.profileGC, ["-?"]), tuple(BuildOption.betterC, ["-betterC"]), tuple(BuildOption._docs, ["-Dd=docs"]), tuple(BuildOption._ddox, ["-Xf=docs.json", "-Dd=__dummy_docs"]), ]; @property string name() const { return "ldc"; } enum ldcVersionRe = `^version\s+v?(\d+\.\d+\.\d+[A-Za-z0-9.+-]*)`; unittest { import std.regex : matchFirst, regex; auto probe = ` binary /usr/bin/ldc2 version 1.11.0 (DMD v2.081.2, LLVM 6.0.1) config /etc/ldc2.conf (x86_64-pc-linux-gnu) `; auto re = regex(ldcVersionRe, "m"); auto c = matchFirst(probe, re); assert(c && c.length > 1 && c[1] == "1.11.0"); } string determineVersion(string compiler_binary, string verboseOutput) { import std.regex : matchFirst, regex; auto ver = matchFirst(verboseOutput, regex(ldcVersionRe, "m")); return ver && ver.length > 1 ? ver[1] : null; } BuildPlatform determinePlatform(ref BuildSettings settings, string compiler_binary, string arch_override) { string[] arch_flags; switch (arch_override) { case "": break; case "x86": arch_flags = ["-march=x86"]; break; case "x86_64": arch_flags = ["-march=x86-64"]; break; default: if (arch_override.canFind('-')) arch_flags = ["-mtriple="~arch_override]; else throw new Exception("Unsupported architecture: "~arch_override); break; } settings.addDFlags(arch_flags); return probePlatform( compiler_binary, arch_flags ~ ["-c", "-o-", "-v"], arch_override ); } void prepareBuildSettings(ref BuildSettings settings, in ref BuildPlatform platform, BuildSetting fields = BuildSetting.all) const { enforceBuildRequirements(settings); if (!(fields & BuildSetting.options)) { foreach (t; s_options) if (settings.options & t[0]) settings.addDFlags(t[1]); } // since LDC always outputs multiple object files, avoid conflicts by default settings.addDFlags("-oq", "-od=.dub/obj"); if (!(fields & BuildSetting.versions)) { settings.addDFlags(settings.versions.map!(s => "-d-version="~s)().array()); settings.versions = null; } if (!(fields & BuildSetting.debugVersions)) { settings.addDFlags(settings.debugVersions.map!(s => "-d-debug="~s)().array()); settings.debugVersions = null; } if (!(fields & BuildSetting.importPaths)) { settings.addDFlags(settings.importPaths.map!(s => "-I"~s)().array()); settings.importPaths = null; } if (!(fields & BuildSetting.stringImportPaths)) { settings.addDFlags(settings.stringImportPaths.map!(s => "-J"~s)().array()); settings.stringImportPaths = null; } if (!(fields & BuildSetting.sourceFiles)) { settings.addDFlags(settings.sourceFiles); settings.sourceFiles = null; } if (!(fields & BuildSetting.libs)) { resolveLibs(settings, platform); settings.addLFlags(settings.libs.map!(l => "-l"~l)().array()); } if (!(fields & BuildSetting.lflags)) { settings.addDFlags(lflagsToDFlags(settings.lflags)); settings.lflags = null; } if (settings.options & BuildOption.pic) settings.addDFlags("-relocation-model=pic"); assert(fields & BuildSetting.dflags); assert(fields & BuildSetting.copyFiles); } void extractBuildOptions(ref BuildSettings settings) const { Appender!(string[]) newflags; next_flag: foreach (f; settings.dflags) { foreach (t; s_options) if (t[1].canFind(f)) { settings.options |= t[0]; continue next_flag; } if (f.startsWith("-d-version=")) settings.addVersions(f[11 .. $]); else if (f.startsWith("-d-debug=")) settings.addDebugVersions(f[9 .. $]); else newflags ~= f; } settings.dflags = newflags.data; } string getTargetFileName(in BuildSettings settings, in BuildPlatform platform) const { assert(settings.targetName.length > 0, "No target name set."); const p = platform.platform; final switch (settings.targetType) { case TargetType.autodetect: assert(false, "Configurations must have a concrete target type."); case TargetType.none: return null; case TargetType.sourceLibrary: return null; case TargetType.executable: if (p.canFind("windows")) return settings.targetName ~ ".exe"; else if (p.canFind("wasm")) return settings.targetName ~ ".wasm"; else return settings.targetName.idup; case TargetType.library: case TargetType.staticLibrary: if (p.canFind("windows") && !p.canFind("mingw")) return settings.targetName ~ ".lib"; else return "lib" ~ settings.targetName ~ ".a"; case TargetType.dynamicLibrary: if (p.canFind("windows")) return settings.targetName ~ ".dll"; else if (p.canFind("osx")) return "lib" ~ settings.targetName ~ ".dylib"; else return "lib" ~ settings.targetName ~ ".so"; case TargetType.object: if (p.canFind("windows")) return settings.targetName ~ ".obj"; else return settings.targetName ~ ".o"; } } void setTarget(ref BuildSettings settings, in BuildPlatform platform, string tpath = null) const { final switch (settings.targetType) { case TargetType.autodetect: assert(false, "Invalid target type: autodetect"); case TargetType.none: assert(false, "Invalid target type: none"); case TargetType.sourceLibrary: assert(false, "Invalid target type: sourceLibrary"); case TargetType.executable: break; case TargetType.library: case TargetType.staticLibrary: settings.addDFlags("-lib"); break; case TargetType.dynamicLibrary: settings.addDFlags("-shared"); break; case TargetType.object: settings.addDFlags("-c"); break; } if (tpath is null) tpath = (NativePath(settings.targetPath) ~ getTargetFileName(settings, platform)).toNativeString(); settings.addDFlags("-of"~tpath); } void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback) { auto res_file = getTempFile("dub-build", ".rsp"); const(string)[] args = settings.dflags; if (platform.frontendVersion >= 2066) args ~= "-vcolumns"; std.file.write(res_file.toNativeString(), escapeArgs(args).join("\n")); logDiagnostic("%s %s", platform.compilerBinary, escapeArgs(args).join(" ")); invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback); } void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback) { import std.string; auto tpath = NativePath(settings.targetPath) ~ getTargetFileName(settings, platform); auto args = ["-of"~tpath.toNativeString()]; args ~= objects; args ~= settings.sourceFiles; if (platform.platform.canFind("linux")) args ~= "-L--no-as-needed"; // avoids linker errors due to libraries being specified in the wrong order args ~= lflagsToDFlags(settings.lflags); args ~= settings.dflags.filter!(f => isLinkerDFlag(f)).array; auto res_file = getTempFile("dub-build", ".lnk"); std.file.write(res_file.toNativeString(), escapeArgs(args).join("\n")); logDiagnostic("%s %s", platform.compilerBinary, escapeArgs(args).join(" ")); invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback); } string[] lflagsToDFlags(in string[] lflags) const { return map!(f => "-L"~f)(lflags.filter!(f => f != "")()).array(); } private auto escapeArgs(in string[] args) { return args.map!(s => s.canFind(' ') ? "\""~s~"\"" : s); } private static bool isLinkerDFlag(string arg) { switch (arg) { case "-g", "-gc", "-m32", "-m64", "-shared", "-lib", "-betterC", "-disable-linker-strip-dead", "-static": return true; default: return arg.startsWith("-L") || arg.startsWith("-Xcc=") || arg.startsWith("-defaultlib=") || arg.startsWith("-flto") || arg.startsWith("-fsanitize=") || arg.startsWith("-link-") || arg.startsWith("-linker=") || arg.startsWith("-march=") || arg.startsWith("-mscrtlib=") || arg.startsWith("-mtriple="); } } } dub-1.19.0/source/dub/compilers/utils.d000066400000000000000000000336471360435400500177450ustar00rootroot00000000000000/** Utility functionality for compiler class implementations. Copyright: © 2013-2016 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.compilers.utils; import dub.compilers.buildsettings; import dub.platform : BuildPlatform, archCheck, compilerCheck, platformCheck; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import std.algorithm : canFind, endsWith, filter; /** Alters the build options to comply with the specified build requirements. And enabled options that do not comply will get disabled. */ void enforceBuildRequirements(ref BuildSettings settings) { settings.addOptions(BuildOption.warningsAsErrors); if (settings.requirements & BuildRequirement.allowWarnings) { settings.options &= ~BuildOption.warningsAsErrors; settings.options |= BuildOption.warnings; } if (settings.requirements & BuildRequirement.silenceWarnings) settings.options &= ~(BuildOption.warningsAsErrors|BuildOption.warnings); if (settings.requirements & BuildRequirement.disallowDeprecations) { settings.options &= ~(BuildOption.ignoreDeprecations|BuildOption.deprecationWarnings); settings.options |= BuildOption.deprecationErrors; } if (settings.requirements & BuildRequirement.silenceDeprecations) { settings.options &= ~(BuildOption.deprecationErrors|BuildOption.deprecationWarnings); settings.options |= BuildOption.ignoreDeprecations; } if (settings.requirements & BuildRequirement.disallowInlining) settings.options &= ~BuildOption.inline; if (settings.requirements & BuildRequirement.disallowOptimization) settings.options &= ~BuildOption.optimize; if (settings.requirements & BuildRequirement.requireBoundsCheck) settings.options &= ~BuildOption.noBoundsCheck; if (settings.requirements & BuildRequirement.requireContracts) settings.options &= ~BuildOption.releaseMode; if (settings.requirements & BuildRequirement.relaxProperties) settings.options &= ~BuildOption.property; } /** Determines if a specific file name has the extension of a linker file. Linker files include static/dynamic libraries, resource files, object files and DLL definition files. */ bool isLinkerFile(in ref BuildPlatform platform, string f) { import std.path; switch (extension(f)) { default: return false; case ".lib", ".obj", ".res", ".def": return platform.platform.canFind("windows"); case ".a", ".o", ".so", ".dylib": return !platform.platform.canFind("windows"); } } unittest { BuildPlatform p; p.platform = ["windows"]; assert(isLinkerFile(p, "test.obj")); assert(isLinkerFile(p, "test.lib")); assert(isLinkerFile(p, "test.res")); assert(!isLinkerFile(p, "test.o")); assert(!isLinkerFile(p, "test.d")); p.platform = ["something else"]; assert(isLinkerFile(p, "test.o")); assert(isLinkerFile(p, "test.a")); assert(isLinkerFile(p, "test.so")); assert(isLinkerFile(p, "test.dylib")); assert(!isLinkerFile(p, "test.obj")); assert(!isLinkerFile(p, "test.d")); } /** Replaces each referenced import library by the appropriate linker flags. This function tries to invoke "pkg-config" if possible and falls back to direct flag translation if that fails. */ void resolveLibs(ref BuildSettings settings, in ref BuildPlatform platform) { import std.string : format; import std.array : array; if (settings.libs.length == 0) return; if (settings.targetType == TargetType.library || settings.targetType == TargetType.staticLibrary) { logDiagnostic("Ignoring all import libraries for static library build."); settings.libs = null; if (platform.platform.canFind("windows")) settings.sourceFiles = settings.sourceFiles.filter!(f => !f.endsWith(".lib")).array; } version (Posix) { import std.algorithm : any, map, partition, startsWith; import std.array : array, join, split; import std.exception : enforce; import std.process : execute; try { enum pkgconfig_bin = "pkg-config"; bool exists(string lib) { return execute([pkgconfig_bin, "--exists", lib]).status == 0; } auto pkgconfig_libs = settings.libs.partition!(l => !exists(l)); pkgconfig_libs ~= settings.libs[0 .. $ - pkgconfig_libs.length] .partition!(l => !exists("lib"~l)).map!(l => "lib"~l).array; settings.libs = settings.libs[0 .. $ - pkgconfig_libs.length]; if (pkgconfig_libs.length) { logDiagnostic("Using pkg-config to resolve library flags for %s.", pkgconfig_libs.join(", ")); auto libflags = execute([pkgconfig_bin, "--libs"] ~ pkgconfig_libs); enforce(libflags.status == 0, format("pkg-config exited with error code %s: %s", libflags.status, libflags.output)); foreach (f; libflags.output.split()) { if (f.startsWith("-L-L")) { settings.addLFlags(f[2 .. $]); } else if (f.startsWith("-defaultlib")) { settings.addDFlags(f); } else if (f.startsWith("-L-defaultlib")) { settings.addDFlags(f[2 .. $]); } else if (f.startsWith("-pthread")) { settings.addLFlags("-lpthread"); } else if (f.startsWith("-L-l")) { settings.addLFlags(f[2 .. $].split(",")); } else if (f.startsWith("-Wl,")) settings.addLFlags(f[4 .. $].split(",")); else settings.addLFlags(f); } } if (settings.libs.length) logDiagnostic("Using direct -l... flags for %s.", settings.libs.array.join(", ")); } catch (Exception e) { logDiagnostic("pkg-config failed: %s", e.msg); logDiagnostic("Falling back to direct -l... flags."); } } } /** Searches the given list of compiler flags for ones that have a generic equivalent. Certain compiler flags should, instead of using compiler-specific syntax, be specified as build options (`BuildOptions`) or built requirements (`BuildRequirements`). This function will output warning messages to assist the user in making the best choice. */ void warnOnSpecialCompilerFlags(string[] compiler_flags, BuildOptions options, string package_name, string config_name) { import std.algorithm : any, endsWith, startsWith; import std.range : empty; struct SpecialFlag { string[] flags; string alternative; } static immutable SpecialFlag[] s_specialFlags = [ {["-c", "-o-"], "Automatically issued by DUB, do not specify in dub.json"}, {["-w", "-Wall", "-Werr"], `Use "buildRequirements" to control warning behavior`}, {["-property", "-fproperty"], "Using this flag may break building of dependencies and it will probably be removed from DMD in the future"}, {["-wi"], `Use the "buildRequirements" field to control warning behavior`}, {["-d", "-de", "-dw"], `Use the "buildRequirements" field to control deprecation behavior`}, {["-of"], `Use "targetPath" and "targetName" to customize the output file`}, {["-debug", "-fdebug", "-g"], "Call dub with --build=debug"}, {["-release", "-frelease", "-O", "-inline"], "Call dub with --build=release"}, {["-unittest", "-funittest"], "Call dub with --build=unittest"}, {["-lib"], `Use {"targetType": "staticLibrary"} or let dub manage this`}, {["-D"], "Call dub with --build=docs or --build=ddox"}, {["-X"], "Call dub with --build=ddox"}, {["-cov"], "Call dub with --build=cov or --build=unittest-cov"}, {["-profile"], "Call dub with --build=profile"}, {["-version="], `Use "versions" to specify version constants in a compiler independent way`}, {["-debug="], `Use "debugVersions" to specify version constants in a compiler independent way`}, {["-I"], `Use "importPaths" to specify import paths in a compiler independent way`}, {["-J"], `Use "stringImportPaths" to specify import paths in a compiler independent way`}, {["-m32", "-m64", "-m32mscoff"], `Use --arch=x86/--arch=x86_64/--arch=x86_mscoff to specify the target architecture, e.g. 'dub build --arch=x86_64'`} ]; struct SpecialOption { BuildOption[] flags; string alternative; } static immutable SpecialOption[] s_specialOptions = [ {[BuildOption.debugMode], "Call DUB with --build=debug"}, {[BuildOption.releaseMode], "Call DUB with --build=release"}, {[BuildOption.coverage], "Call DUB with --build=cov or --build=unittest-cov"}, {[BuildOption.debugInfo], "Call DUB with --build=debug"}, {[BuildOption.inline], "Call DUB with --build=release"}, {[BuildOption.noBoundsCheck], "Call DUB with --build=release-nobounds"}, {[BuildOption.optimize], "Call DUB with --build=release"}, {[BuildOption.profile], "Call DUB with --build=profile"}, {[BuildOption.unittests], "Call DUB with --build=unittest"}, {[BuildOption.syntaxOnly], "Call DUB with --build=syntax"}, {[BuildOption.warnings, BuildOption.warningsAsErrors], "Use \"buildRequirements\" to control the warning level"}, {[BuildOption.ignoreDeprecations, BuildOption.deprecationWarnings, BuildOption.deprecationErrors], "Use \"buildRequirements\" to control the deprecation warning level"}, {[BuildOption.property], "This flag is deprecated and has no effect"} ]; bool got_preamble = false; void outputPreamble() { if (got_preamble) return; got_preamble = true; logWarn(""); if (config_name.empty) logWarn("## Warning for package %s ##", package_name); else logWarn("## Warning for package %s, configuration %s ##", package_name, config_name); logWarn(""); logWarn("The following compiler flags have been specified in the package description"); logWarn("file. They are handled by DUB and direct use in packages is discouraged."); logWarn("Alternatively, you can set the DFLAGS environment variable to pass custom flags"); logWarn("to the compiler, or use one of the suggestions below:"); logWarn(""); } foreach (f; compiler_flags) { foreach (sf; s_specialFlags) { if (sf.flags.any!(sff => f == sff || (sff.endsWith("=") && f.startsWith(sff)))) { outputPreamble(); logWarn("%s: %s", f, sf.alternative); break; } } } foreach (sf; s_specialOptions) { foreach (f; sf.flags) { if (options & f) { outputPreamble(); logWarn("%s: %s", f, sf.alternative); break; } } } if (got_preamble) logWarn(""); } /** Turn a DMD-like version (e.g. 2.082.1) into a SemVer-like version (e.g. 2.82.1). The function accepts a dependency operator prefix and some text postfix. Prefix and postfix are returned verbatim. Params: ver = version string, possibly with a dependency operator prefix and some test postfix. Returns: A Semver compliant string */ package(dub) string dmdLikeVersionToSemverLike(string ver) { import std.algorithm : countUntil, joiner, map, skipOver, splitter; import std.array : join, split; import std.ascii : isDigit; import std.conv : text; import std.exception : enforce; import std.functional : not; import std.range : padRight; const start = ver.countUntil!isDigit; enforce(start != -1, "Invalid semver: "~ver); const prefix = ver[0 .. start]; ver = ver[start .. $]; const end = ver.countUntil!(c => !c.isDigit && c != '.'); const postfix = end == -1 ? null : ver[end .. $]; auto verStr = ver[0 .. $-postfix.length]; auto comps = verStr .splitter(".") .map!((a) { if (a.length > 1) a.skipOver("0"); return a;}) .padRight("0", 3); return text(prefix, comps.joiner("."), postfix); } /// unittest { assert(dmdLikeVersionToSemverLike("2.082.1") == "2.82.1"); assert(dmdLikeVersionToSemverLike("2.082.0") == "2.82.0"); assert(dmdLikeVersionToSemverLike("2.082") == "2.82.0"); assert(dmdLikeVersionToSemverLike("~>2.082") == "~>2.82.0"); assert(dmdLikeVersionToSemverLike("~>2.082-beta1") == "~>2.82.0-beta1"); assert(dmdLikeVersionToSemverLike("2.4.6") == "2.4.6"); assert(dmdLikeVersionToSemverLike("2.4.6-alpha12") == "2.4.6-alpha12"); } private enum probeBeginMark = "__dub_probe_begin__"; private enum probeEndMark = "__dub_probe_end__"; /** Generate a file that will give, at compile time, information about the compiler (architecture, frontend version...) See_Also: `readPlatformProbe` */ NativePath generatePlatformProbeFile() { import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; import dub.internal.utils; import std.string : format; // try to not use phobos in the probe to avoid long import times enum probe = q{ module dub_platform_probe; template toString(int v) { enum toString = v.stringof; } string stringArray(string[] ary) { string res; foreach (i, e; ary) { if (i) res ~= ", "; res ~= '"' ~ e ~ '"'; } return res; } pragma(msg, `%1$s` ~ '\n' ~ `{` ~ '\n' ~ ` "compiler": "`~ determineCompiler() ~ `",` ~ '\n' ~ ` "frontendVersion": ` ~ toString!__VERSION__ ~ `,` ~ '\n' ~ ` "compilerVendor": "` ~ __VENDOR__ ~ `",` ~ '\n' ~ ` "platform": [` ~ '\n' ~ ` ` ~ determinePlatform().stringArray ~ '\n' ~ ` ],` ~ '\n' ~ ` "architecture": [` ~ '\n' ~ ` ` ~ determineArchitecture().stringArray ~ '\n' ~ ` ],` ~ '\n' ~ `}` ~ '\n' ~ `%2$s`); string[] determinePlatform() { %3$s } string[] determineArchitecture() { %4$s } string determineCompiler() { %5$s } }.format(probeBeginMark, probeEndMark, platformCheck, archCheck, compilerCheck); auto path = getTempFile("dub_platform_probe", ".d"); auto fil = openFile(path, FileMode.createTrunc); fil.write(probe); return path; } /** Processes the JSON output generated by compiling the platform probe file. See_Also: `generatePlatformProbeFile`. */ BuildPlatform readPlatformJsonProbe(string output) { import std.algorithm : map; import std.array : array; import std.exception : enforce; import std.string; // work around possible additional output of the compiler auto idx1 = output.indexOf(probeBeginMark); auto idx2 = output.lastIndexOf(probeEndMark); enforce(idx1 >= 0 && idx1 < idx2, "Unexpected platform information output - does not contain a JSON object."); output = output[idx1+probeBeginMark.length .. idx2]; import dub.internal.vibecompat.data.json; auto json = parseJsonString(output); BuildPlatform build_platform; build_platform.platform = json["platform"].get!(Json[]).map!(e => e.get!string()).array(); build_platform.architecture = json["architecture"].get!(Json[]).map!(e => e.get!string()).array(); build_platform.compiler = json["compiler"].get!string; build_platform.frontendVersion = json["frontendVersion"].get!int; return build_platform; } dub-1.19.0/source/dub/dependency.d000066400000000000000000000667051360435400500167270ustar00rootroot00000000000000/** Dependency specification functionality. Copyright: © 2012-2013 Matthias Dondorff, © 2012-2016 Sönke Ludwig License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Matthias Dondorff, Sönke Ludwig */ module dub.dependency; import dub.internal.utils; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.url; import dub.package_; import dub.semver; import std.algorithm; import std.array; import std.exception; import std.regex; import std.string; import std.typecons; static import std.compiler; /** Encapsulates the name of a package along with its dependency specification. */ struct PackageDependency { /// Name of the referenced package. string name; /// Dependency specification used to select a particular version of the package. Dependency spec; } /** Represents a dependency specification. A dependency specification either represents a specific version or version range, or a path to a package. In addition to that it has `optional` and `default_` flags to control how non-mandatory dependencies are handled. The package name is notably not part of the dependency specification. */ struct Dependency { @safe: private { // Shortcut to create >=0.0.0 enum ANY_IDENT = "*"; bool m_inclusiveA = true; // A comparison > (true) or >= (false) Version m_versA; bool m_inclusiveB = true; // B comparison < (true) or <= (false) Version m_versB; NativePath m_path; bool m_optional = false; bool m_default = false; } /// A Dependency, which matches every valid version. static @property Dependency any() { return Dependency(ANY_IDENT); } /// An invalid dependency (with no possible version matches). static @property Dependency invalid() { Dependency ret; ret.m_versA = Version.maxRelease; ret.m_versB = Version.minRelease; return ret; } /** Constructs a new dependency specification from a string See the `versionSpec` property for a description of the accepted contents of that string. */ this(string spec) { this.versionSpec = spec; } /** Constructs a new dependency specification that matches a specific version. */ this(const Version ver) { m_inclusiveA = m_inclusiveB = true; m_versA = ver; m_versB = ver; } /** Constructs a new dependency specification that matches a specific path. */ this(NativePath path) { this(ANY_IDENT); m_path = path; } /// If set, overrides any version based dependency selection. @property void path(NativePath value) { m_path = value; } /// ditto @property NativePath path() const { return m_path; } /// Determines if the dependency is required or optional. @property bool optional() const { return m_optional; } /// ditto @property void optional(bool optional) { m_optional = optional; } /// Determines if an optional dependency should be chosen by default. @property bool default_() const { return m_default; } /// ditto @property void default_(bool value) { m_default = value; } /// Returns true $(I iff) the version range only matches a specific version. @property bool isExactVersion() const { return m_versA == m_versB; } /// Returns the exact version matched by the version range. @property Version version_() const { enforce(m_versA == m_versB, "Dependency "~this.versionSpec~" is no exact version."); return m_versA; } /** Sets/gets the matching version range as a specification string. The acceptable forms for this string are as follows: $(UL $(LI `"1.0.0"` - a single version in SemVer format) $(LI `"==1.0.0"` - alternative single version notation) $(LI `">1.0.0"` - version range with a single bound) $(LI `">1.0.0 <2.0.0"` - version range with two bounds) $(LI `"~>1.0.0"` - a fuzzy version range) $(LI `"~>1.0"` - a fuzzy version range with partial version) $(LI `"^1.0.0"` - semver compatible version range (same version if 0.x.y, ==major >=minor.patch if x.y.z)) $(LI `"^1.0"` - same as ^1.0.0) $(LI `"~master"` - a branch name) $(LI `"*" - match any version (see also `any`)) ) Apart from "$(LT)" and "$(GT)", "$(GT)=" and "$(LT)=" are also valid comparators. */ @property void versionSpec(string ves) { static import std.string; enforce(ves.length > 0); if (ves == ANY_IDENT) { // Any version is good. ves = ">=0.0.0"; } if (ves.startsWith("~>")) { // Shortcut: "~>x.y.z" variant. Last non-zero number will indicate // the base for this so something like this: ">=x.y.z =x.y.z <(x+1).0.0-0 // ^x.y is equivalent to ^x.y.0. m_inclusiveA = true; m_inclusiveB = false; ves = ves[1..$].expandVersion; m_versA = Version(ves); m_versB = Version(bumpIncompatibleVersion(ves) ~ "-0"); } else if (ves[0] == Version.branchPrefix) { m_inclusiveA = true; m_inclusiveB = true; m_versA = m_versB = Version(ves); } else if (std.string.indexOf("><=", ves[0]) == -1) { m_inclusiveA = true; m_inclusiveB = true; m_versA = m_versB = Version(ves); } else { auto cmpa = skipComp(ves); size_t idx2 = std.string.indexOf(ves, " "); if (idx2 == -1) { if (cmpa == "<=" || cmpa == "<") { m_versA = Version.minRelease; m_inclusiveA = true; m_versB = Version(ves); m_inclusiveB = cmpa == "<="; } else if (cmpa == ">=" || cmpa == ">") { m_versA = Version(ves); m_inclusiveA = cmpa == ">="; m_versB = Version.maxRelease; m_inclusiveB = true; } else { // Converts "==" to ">=a&&<=a", which makes merging easier m_versA = m_versB = Version(ves); m_inclusiveA = m_inclusiveB = true; } } else { enforce(cmpa == ">" || cmpa == ">=", "First comparison operator expected to be either > or >=, not "~cmpa); assert(ves[idx2] == ' '); m_versA = Version(ves[0..idx2]); m_inclusiveA = cmpa == ">="; string v2 = ves[idx2+1..$]; auto cmpb = skipComp(v2); enforce(cmpb == "<" || cmpb == "<=", "Second comparison operator expected to be either < or <=, not "~cmpb); m_versB = Version(v2); m_inclusiveB = cmpb == "<="; enforce(!m_versA.isBranch && !m_versB.isBranch, format("Cannot compare branches: %s", ves)); enforce(m_versA <= m_versB, "First version must not be greater than the second one."); } } } /// ditto @property string versionSpec() const { static import std.string; string r; if (this == invalid) return "invalid"; if (m_versA == m_versB && m_inclusiveA && m_inclusiveB) { // Special "==" case if (m_versA == Version.masterBranch) return "~master"; else return m_versA.toString(); } // "~>", "^" case if (m_inclusiveA && !m_inclusiveB && !m_versA.isBranch) { auto vs = m_versA.toString(); auto i1 = std.string.indexOf(vs, '-'), i2 = std.string.indexOf(vs, '+'); auto i12 = i1 >= 0 ? i2 >= 0 ? i1 < i2 ? i1 : i2 : i1 : i2; auto va = i12 >= 0 ? vs[0 .. i12] : vs; auto parts = va.splitter('.').array; assert(parts.length == 3, "Version string with a digit group count != 3: "~va); foreach (i; 0 .. 3) { auto vp = parts[0 .. i+1].join("."); auto ve = Version(expandVersion(vp)); auto veb = Version(bumpVersion(vp) ~ "-0"); if (ve == m_versA && veb == m_versB) return "~>" ~ vp; auto veb2 = Version(bumpIncompatibleVersion(expandVersion(vp)) ~ "-0"); if (ve == m_versA && veb2 == m_versB) return "^" ~ vp; } } if (m_versA != Version.minRelease) r = (m_inclusiveA ? ">=" : ">") ~ m_versA.toString(); if (m_versB != Version.maxRelease) r ~= (r.length==0 ? "" : " ") ~ (m_inclusiveB ? "<=" : "<") ~ m_versB.toString(); if (m_versA == Version.minRelease && m_versB == Version.maxRelease) r = ">=0.0.0"; return r; } /** Returns a modified dependency that gets mapped to a given path. This function will return an unmodified `Dependency` if it is not path based. Otherwise, the given `path` will be prefixed to the existing path. */ Dependency mapToPath(NativePath path) const @trusted { // NOTE Path is @system in vibe.d 0.7.x and in the compatibility layer if (m_path.empty || m_path.absolute) return this; else { Dependency ret = this; ret.path = path ~ ret.path; return ret; } } /** Returns a human-readable string representation of the dependency specification. */ string toString()() const { auto ret = versionSpec; if (optional) { if (default_) ret ~= " (optional, default)"; else ret ~= " (optional)"; } // NOTE Path is @system in vibe.d 0.7.x and in the compatibility layer () @trusted { if (!path.empty) ret ~= " @"~path.toNativeString(); } (); return ret; } /** Returns a JSON representation of the dependency specification. Simple specifications will be represented as a single specification string (`versionSpec`), while more complex specifications will be represented as a JSON object with optional "version", "path", "optional" and "default" fields. */ Json toJson() const @trusted { // NOTE Path and Json is @system in vibe.d 0.7.x and in the compatibility layer Json json; if( path.empty && !optional ){ json = Json(this.versionSpec); } else { json = Json.emptyObject; json["version"] = this.versionSpec; if (!path.empty) json["path"] = path.toString(); if (optional) json["optional"] = true; if (default_) json["default"] = true; } return json; } @trusted unittest { Dependency d = Dependency("==1.0.0"); assert(d.toJson() == Json("1.0.0"), "Failed: " ~ d.toJson().toPrettyString()); d = fromJson((fromJson(d.toJson())).toJson()); assert(d == Dependency("1.0.0")); assert(d.toJson() == Json("1.0.0"), "Failed: " ~ d.toJson().toPrettyString()); } /** Constructs a new `Dependency` from its JSON representation. See `toJson` for a description of the JSON format. */ static Dependency fromJson(Json verspec) @trusted { // NOTE Path and Json is @system in vibe.d 0.7.x and in the compatibility layer Dependency dep; if( verspec.type == Json.Type.object ){ if( auto pp = "path" in verspec ) { if (auto pv = "version" in verspec) logDiagnostic("Ignoring version specification (%s) for path based dependency %s", pv.get!string, pp.get!string); dep = Dependency.any; dep.path = NativePath(verspec["path"].get!string); } else { enforce("version" in verspec, "No version field specified!"); auto ver = verspec["version"].get!string; // Using the string to be able to specify a range of versions. dep = Dependency(ver); } if (auto po = "optional" in verspec) dep.optional = po.get!bool; if (auto po = "default" in verspec) dep.default_ = po.get!bool; } else { // canonical "package-id": "version" dep = Dependency(verspec.get!string); } return dep; } @trusted unittest { assert(fromJson(parseJsonString("\">=1.0.0 <2.0.0\"")) == Dependency(">=1.0.0 <2.0.0")); Dependency parsed = fromJson(parseJsonString(` { "version": "2.0.0", "optional": true, "default": true, "path": "path/to/package" } `)); Dependency d = Dependency.any; // supposed to ignore the version spec d.optional = true; d.default_ = true; d.path = NativePath("path/to/package"); assert(d == parsed); // optional and path not checked by opEquals. assert(d.optional == parsed.optional); assert(d.default_ == parsed.default_); assert(d.path == parsed.path); } /** Compares dependency specifications. These methods are suitable for equality comparisons, as well as for using `Dependency` as a key in hash or tree maps. */ bool opEquals(const Dependency o) const { // TODO(mdondorff): Check if not comparing the path is correct for all clients. return o.m_inclusiveA == m_inclusiveA && o.m_inclusiveB == m_inclusiveB && o.m_versA == m_versA && o.m_versB == m_versB && o.m_optional == m_optional && o.m_default == m_default; } /// ditto int opCmp(const Dependency o) const { if (m_inclusiveA != o.m_inclusiveA) return m_inclusiveA < o.m_inclusiveA ? -1 : 1; if (m_inclusiveB != o.m_inclusiveB) return m_inclusiveB < o.m_inclusiveB ? -1 : 1; if (m_versA != o.m_versA) return m_versA < o.m_versA ? -1 : 1; if (m_versB != o.m_versB) return m_versB < o.m_versB ? -1 : 1; if (m_optional != o.m_optional) return m_optional ? -1 : 1; return 0; } /// ditto size_t toHash() const nothrow @trusted { try { size_t hash = 0; hash = m_inclusiveA.hashOf(hash); hash = m_versA.toString().hashOf(hash); hash = m_inclusiveB.hashOf(hash); hash = m_versB.toString().hashOf(hash); hash = m_optional.hashOf(hash); hash = m_default.hashOf(hash); return hash; } catch (Exception) assert(false); } /** Determines if this dependency specification is valid. A specification is valid if it can match at least one version. */ bool valid() const { return m_versA <= m_versB && doCmp(m_inclusiveA && m_inclusiveB, m_versA, m_versB); } /** Determines if this dependency specification matches arbitrary versions. This is true in particular for the `any` constant. */ bool matchesAny() const { return m_inclusiveA && m_inclusiveB && m_versA.toString() == "0.0.0" && m_versB == Version.maxRelease; } unittest { assert(Dependency("*").matchesAny); assert(!Dependency(">0.0.0").matchesAny); assert(!Dependency(">=1.0.0").matchesAny); assert(!Dependency("<1.0.0").matchesAny); } /** Tests if the specification matches a specific version. */ bool matches(string vers) const { return matches(Version(vers)); } /// ditto bool matches(const(Version) v) const { return matches(v); } /// ditto bool matches(ref const(Version) v) const { if (this.matchesAny) return true; //logDebug(" try match: %s with: %s", v, this); // Master only matches master if(m_versA.isBranch) { enforce(m_versA == m_versB); return m_versA == v; } if(v.isBranch || m_versA.isBranch) return m_versA == v; if( !doCmp(m_inclusiveA, m_versA, v) ) return false; if( !doCmp(m_inclusiveB, v, m_versB) ) return false; return true; } /** Merges two dependency specifications. The result is a specification that matches the intersection of the set of versions matched by the individual specifications. Note that this result can be invalid (i.e. not match any version). */ Dependency merge(ref const(Dependency) o) const { if (this.matchesAny) return o; if (o.matchesAny) return this; if (m_versA.isBranch != o.m_versA.isBranch) return invalid; if (m_versB.isBranch != o.m_versB.isBranch) return invalid; if (m_versA.isBranch) return m_versA == o.m_versA ? this : invalid; // NOTE Path is @system in vibe.d 0.7.x and in the compatibility layer if (() @trusted { return this.path != o.path; } ()) return invalid; int acmp = m_versA.opCmp(o.m_versA); int bcmp = m_versB.opCmp(o.m_versB); Dependency d = this; d.m_inclusiveA = !m_inclusiveA && acmp >= 0 ? false : o.m_inclusiveA; d.m_versA = acmp > 0 ? m_versA : o.m_versA; d.m_inclusiveB = !m_inclusiveB && bcmp <= 0 ? false : o.m_inclusiveB; d.m_versB = bcmp < 0 ? m_versB : o.m_versB; d.m_optional = m_optional && o.m_optional; if (!d.valid) return invalid; return d; } private static bool isDigit(char ch) { return ch >= '0' && ch <= '9'; } private static string skipComp(ref string c) { size_t idx = 0; while (idx < c.length && !isDigit(c[idx]) && c[idx] != Version.branchPrefix) idx++; enforce(idx < c.length, "Expected version number in version spec: "~c); string cmp = idx==c.length-1||idx==0? ">=" : c[0..idx]; c = c[idx..$]; switch(cmp) { default: enforce(false, "No/Unknown comparison specified: '"~cmp~"'"); return ">="; case ">=": goto case; case ">": goto case; case "<=": goto case; case "<": goto case; case "==": return cmp; } } private static bool doCmp(bool inclusive, ref const Version a, ref const Version b) { return inclusive ? a <= b : a < b; } } unittest { Dependency a = Dependency(">=1.1.0"), b = Dependency(">=1.3.0"); assert (a.merge(b).valid() && a.merge(b).versionSpec == ">=1.3.0", a.merge(b).toString()); assertThrown(Dependency("<=2.0.0 >=1.0.0")); assertThrown(Dependency(">=2.0.0 <=1.0.0")); a = Dependency(">=1.0.0 <=5.0.0"); b = Dependency(">=2.0.0"); assert (a.merge(b).valid() && a.merge(b).versionSpec == ">=2.0.0 <=5.0.0", a.merge(b).toString()); assertThrown(a = Dependency(">1.0.0 ==5.0.0"), "Construction is invalid"); a = Dependency(">1.0.0"); b = Dependency("<2.0.0"); assert (a.merge(b).valid(), a.merge(b).toString()); assert (a.merge(b).versionSpec == ">1.0.0 <2.0.0", a.merge(b).toString()); a = Dependency(">2.0.0"); b = Dependency("<1.0.0"); assert (!(a.merge(b)).valid(), a.merge(b).toString()); a = Dependency(">=2.0.0"); b = Dependency("<=1.0.0"); assert (!(a.merge(b)).valid(), a.merge(b).toString()); a = Dependency("==2.0.0"); b = Dependency("==1.0.0"); assert (!(a.merge(b)).valid(), a.merge(b).toString()); a = Dependency("1.0.0"); b = Dependency("==1.0.0"); assert (a == b); a = Dependency("<=2.0.0"); b = Dependency("==1.0.0"); Dependency m = a.merge(b); assert (m.valid(), m.toString()); assert (m.matches(Version("1.0.0"))); assert (!m.matches(Version("1.1.0"))); assert (!m.matches(Version("0.0.1"))); // branches / head revisions a = Dependency(Version.masterBranch); assert(a.valid()); assert(a.matches(Version.masterBranch)); b = Dependency(Version.masterBranch); m = a.merge(b); assert(m.matches(Version.masterBranch)); //assertThrown(a = Dependency(Version.MASTER_STRING ~ " <=1.0.0"), "Construction invalid"); assertThrown(a = Dependency(">=1.0.0 " ~ Version.masterBranch.toString()), "Construction invalid"); immutable string branch1 = Version.branchPrefix ~ "Branch1"; immutable string branch2 = Version.branchPrefix ~ "Branch2"; //assertThrown(a = Dependency(branch1 ~ " " ~ branch2), "Error: '" ~ branch1 ~ " " ~ branch2 ~ "' succeeded"); //assertThrown(a = Dependency(Version.MASTER_STRING ~ " " ~ branch1), "Error: '" ~ Version.MASTER_STRING ~ " " ~ branch1 ~ "' succeeded"); a = Dependency(branch1); b = Dependency(branch2); assert(!a.merge(b).valid, "Shouldn't be able to merge to different branches"); b = a.merge(a); assert(b.valid, "Should be able to merge the same branches. (?)"); assert(a == b); a = Dependency(branch1); assert(a.matches(branch1), "Dependency(branch1) does not match 'branch1'"); assert(a.matches(Version(branch1)), "Dependency(branch1) does not match Version('branch1')"); assert(!a.matches(Version.masterBranch), "Dependency(branch1) matches Version.masterBranch"); assert(!a.matches(branch2), "Dependency(branch1) matches 'branch2'"); assert(!a.matches(Version("1.0.0")), "Dependency(branch1) matches '1.0.0'"); a = Dependency(">=1.0.0"); assert(!a.matches(Version(branch1)), "Dependency(1.0.0) matches 'branch1'"); // Testing optional dependencies. a = Dependency(">=1.0.0"); assert(!a.optional, "Default is not optional."); b = a; assert(!a.merge(b).optional, "Merging two not optional dependencies wrong."); a.optional = true; assert(!a.merge(b).optional, "Merging optional with not optional wrong."); b.optional = true; assert(a.merge(b).optional, "Merging two optional dependencies wrong."); // SemVer's sub identifiers. a = Dependency(">=1.0.0-beta"); assert(!a.matches(Version("1.0.0-alpha")), "Failed: match 1.0.0-alpha with >=1.0.0-beta"); assert(a.matches(Version("1.0.0-beta")), "Failed: match 1.0.0-beta with >=1.0.0-beta"); assert(a.matches(Version("1.0.0")), "Failed: match 1.0.0 with >=1.0.0-beta"); assert(a.matches(Version("1.0.0-rc")), "Failed: match 1.0.0-rc with >=1.0.0-beta"); // Approximate versions. a = Dependency("~>3.0"); b = Dependency(">=3.0.0 <4.0.0-0"); assert(a == b, "Testing failed: " ~ a.toString()); assert(a.matches(Version("3.1.146")), "Failed: Match 3.1.146 with ~>0.1.2"); assert(!a.matches(Version("0.2.0")), "Failed: Match 0.2.0 with ~>0.1.2"); assert(!a.matches(Version("4.0.0-beta.1"))); a = Dependency("~>3.0.0"); assert(a == Dependency(">=3.0.0 <3.1.0-0"), "Testing failed: " ~ a.toString()); a = Dependency("~>3.5"); assert(a == Dependency(">=3.5.0 <4.0.0-0"), "Testing failed: " ~ a.toString()); a = Dependency("~>3.5.0"); assert(a == Dependency(">=3.5.0 <3.6.0-0"), "Testing failed: " ~ a.toString()); assert(!Dependency("~>3.0.0").matches(Version("3.1.0-beta"))); a = Dependency("^0.1.2"); assert(a == Dependency(">=0.1.2 <0.1.3-0")); a = Dependency("^1.2.3"); assert(a == Dependency(">=1.2.3 <2.0.0-0"), "Testing failed: " ~ a.toString()); a = Dependency("^1.2"); assert(a == Dependency(">=1.2.0 <2.0.0-0"), "Testing failed: " ~ a.toString()); a = Dependency("~>0.1.1"); b = Dependency("==0.1.0"); assert(!a.merge(b).valid); b = Dependency("==0.1.9999"); assert(a.merge(b).valid); b = Dependency("==0.2.0"); assert(!a.merge(b).valid); b = Dependency("==0.2.0-beta.1"); assert(!a.merge(b).valid); a = Dependency("~>1.0.1-beta"); b = Dependency(">=1.0.1-beta <1.1.0-0"); assert(a == b, "Testing failed: " ~ a.toString()); assert(a.matches(Version("1.0.1-beta"))); assert(a.matches(Version("1.0.1-beta.6"))); a = Dependency("~d2test"); assert(!a.optional); assert(a.valid); assert(a.version_ == Version("~d2test")); a = Dependency("==~d2test"); assert(!a.optional); assert(a.valid); assert(a.version_ == Version("~d2test")); a = Dependency.any; assert(!a.optional); assert(a.valid); assertThrown(a.version_); assert(a.matches(Version.masterBranch)); assert(a.matches(Version("1.0.0"))); assert(a.matches(Version("0.0.1-pre"))); b = Dependency(">=1.0.1"); assert(b == a.merge(b)); assert(b == b.merge(a)); b = Dependency(Version.masterBranch); assert(a.merge(b) == b); assert(b.merge(a) == b); a.optional = true; assert(a.matches(Version.masterBranch)); assert(a.matches(Version("1.0.0"))); assert(a.matches(Version("0.0.1-pre"))); b = Dependency(">=1.0.1"); assert(b == a.merge(b)); assert(b == b.merge(a)); b = Dependency(Version.masterBranch); assert(a.merge(b) == b); assert(b.merge(a) == b); logDebug("Dependency unittest success."); } unittest { assert(Dependency("~>1.0.4").versionSpec == "~>1.0.4"); assert(Dependency("~>1.4").versionSpec == "~>1.4"); assert(Dependency("~>2").versionSpec == "~>2"); assert(Dependency("~>1.0.4+1.2.3").versionSpec == "~>1.0.4"); assert(Dependency("^0.1.2").versionSpec == "^0.1.2"); assert(Dependency("^1.2.3").versionSpec == "^1.2.3"); assert(Dependency("^1.2").versionSpec == "~>1.2"); // equivalent; prefer ~> } /** Represents a version in semantic version format, or a branch identifier. This can either have the form "~master", where "master" is a branch name, or the form "major.update.bugfix-prerelease+buildmetadata" (see the Semantic Versioning Specification v2.0.0 at http://semver.org/). */ struct Version { @safe: private { static immutable MAX_VERS = "99999.0.0"; static immutable UNKNOWN_VERS = "unknown"; static immutable masterString = "~master"; enum branchPrefix = '~'; string m_version; } static immutable Version minRelease = Version("0.0.0"); static immutable Version maxRelease = Version(MAX_VERS); static immutable Version masterBranch = Version(masterString); static immutable Version unknown = Version(UNKNOWN_VERS); /** Constructs a new `Version` from its string representation. */ this(string vers) { enforce(vers.length > 1, "Version strings must not be empty."); if (vers[0] != branchPrefix && vers.ptr !is UNKNOWN_VERS.ptr) enforce(vers.isValidVersion(), "Invalid SemVer format: " ~ vers); m_version = vers; } /** Constructs a new `Version` from its string representation. This method is equivalent to calling the constructor and is used as an endpoint for the serialization framework. */ static Version fromString(string vers) { return Version(vers); } bool opEquals(const Version oth) const { return opCmp(oth) == 0; } /// Tests if this represents a branch instead of a version. @property bool isBranch() const { return m_version.length > 0 && m_version[0] == branchPrefix; } /// Tests if this represents the master branch "~master". @property bool isMaster() const { return m_version == masterString; } /** Tests if this represents a pre-release version. Note that branches are always considered pre-release versions. */ @property bool isPreRelease() const { if (isBranch) return true; return isPreReleaseVersion(m_version); } /// Tests if this represents the special unknown version constant. @property bool isUnknown() const { return m_version == UNKNOWN_VERS; } /** Compares two versions/branches for precedence. Versions generally have precedence over branches and the master branch has precedence over other branches. Apart from that, versions are compared using SemVer semantics, while branches are compared lexicographically. */ int opCmp(ref const Version other) const { if (isUnknown || other.isUnknown) { throw new Exception("Can't compare unknown versions! (this: %s, other: %s)".format(this, other)); } if (isBranch || other.isBranch) { if(m_version == other.m_version) return 0; if (!isBranch) return 1; else if (!other.isBranch) return -1; if (isMaster) return 1; else if (other.isMaster) return -1; return this.m_version < other.m_version ? -1 : 1; } return compareVersions(m_version, other.m_version); } /// ditto int opCmp(const Version other) const { return opCmp(other); } /// Returns the string representation of the version/branch. string toString() const { return m_version; } } unittest { Version a, b; assertNotThrown(a = Version("1.0.0"), "Constructing Version('1.0.0') failed"); assert(!a.isBranch, "Error: '1.0.0' treated as branch"); assert(a == a, "a == a failed"); assertNotThrown(a = Version(Version.masterString), "Constructing Version("~Version.masterString~"') failed"); assert(a.isBranch, "Error: '"~Version.masterString~"' treated as branch"); assert(a.isMaster); assert(a == Version.masterBranch, "Constructed master version != default master version."); assertNotThrown(a = Version("~BRANCH"), "Construction of branch Version failed."); assert(a.isBranch, "Error: '~BRANCH' not treated as branch'"); assert(!a.isMaster); assert(a == a, "a == a with branch failed"); // opCmp a = Version("1.0.0"); b = Version("1.0.0"); assert(a == b, "a == b with a:'1.0.0', b:'1.0.0' failed"); b = Version("2.0.0"); assert(a != b, "a != b with a:'1.0.0', b:'2.0.0' failed"); a = Version.masterBranch; b = Version("~BRANCH"); assert(a != b, "a != b with a:MASTER, b:'~branch' failed"); assert(a > b); assert(a < Version("0.0.0")); assert(b < Version("0.0.0")); assert(a > Version("~Z")); assert(b < Version("~Z")); // SemVer 2.0.0-rc.2 a = Version("2.0.0-rc.2"); b = Version("2.0.0-rc.3"); assert(a < b, "Failed: 2.0.0-rc.2 < 2.0.0-rc.3"); a = Version("2.0.0-rc.2+build-metadata"); b = Version("2.0.0+build-metadata"); assert(a < b, "Failed: "~a.toString()~"<"~b.toString()); // 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0 Version[] versions; versions ~= Version("1.0.0-alpha"); versions ~= Version("1.0.0-alpha.1"); versions ~= Version("1.0.0-beta.2"); versions ~= Version("1.0.0-beta.11"); versions ~= Version("1.0.0-rc.1"); versions ~= Version("1.0.0"); for(int i=1; i=0; --j) assert(versions[j] < versions[i], "Failed: " ~ versions[j].toString() ~ "<" ~ versions[i].toString()); a = Version.unknown; b = Version.minRelease; assertThrown(a == b, "Failed: compared " ~ a.toString() ~ " with " ~ b.toString() ~ ""); a = Version.unknown; b = Version.unknown; assertThrown(a == b, "Failed: UNKNOWN == UNKNOWN"); assert(Version("1.0.0+a") == Version("1.0.0+b")); } dub-1.19.0/source/dub/dependencyresolver.d000066400000000000000000000377641360435400500205140ustar00rootroot00000000000000/** Dependency configuration/version resolution algorithm. Copyright: © 2014-2018 Sönke Ludwig License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.dependencyresolver; import dub.dependency; import dub.internal.vibecompat.core.log; import std.algorithm : all, canFind, filter, map, sort; import std.array : appender, array, join; import std.conv : to; import std.exception : enforce; import std.typecons : Nullable; import std.string : format, indexOf, lastIndexOf; /** Resolves dependency graph with multiple configurations per package. The term "configuration" can mean any kind of alternative dependency configuration of a package. In particular, it can mean different versions of a package. `CONFIG` is an abstract type denoting a single configuration of a certain package, whereas `CONFIGS` denotes a set of configurations. The representation of both can be freely chosen, so that `CONFIGS` for example can be defined in terms of a version range. */ class DependencyResolver(CONFIGS, CONFIG) { /** Encapsulates a list of outgoing edges in the dependency graph. A value of this type represents a single dependency with multiple possible configurations for the target package. */ static struct TreeNodes { string pack; CONFIGS configs; DependencyType depType = DependencyType.required; size_t toHash() const nothrow @trusted { size_t ret = typeid(string).getHash(&pack); ret ^= typeid(CONFIGS).getHash(&configs); return ret; } bool opEqual(in ref TreeNodes other) const { return pack == other.pack && configs == other.configs; } int opCmp(in ref TreeNodes other) const { if (pack != other.pack) return pack < other.pack ? -1 : 1; if (configs != other.configs) return configs < other.configs ? -1 : 1; return 0; } } /** A single node in the dependency graph. Nodes are a combination of a package and a single package configuration. */ static struct TreeNode { string pack; CONFIG config; size_t toHash() const nothrow @trusted { size_t ret = pack.hashOf(); ret ^= typeid(CONFIG).getHash(&config); return ret; } bool opEqual(in ref TreeNode other) const { return pack == other.pack && config == other.config; } int opCmp(in ref TreeNode other) const { if (pack != other.pack) return pack < other.pack ? -1 : 1; if (config != other.config) return config < other.config ? -1 : 1; return 0; } } CONFIG[string] resolve(TreeNode root, bool throw_on_failure = true) { // Leave the possibility to opt-out from the loop limit import std.process : environment; bool no_loop_limit = environment.get("DUB_NO_RESOLVE_LIMIT") !is null; auto rootbase = root.pack.basePackageName; // build up the dependency graph, eliminating as many configurations/ // versions as possible ResolveContext context; context.configs[rootbase] = [ResolveConfig(root.config, true)]; long loop_counter = no_loop_limit ? long.max : 1_000_000; constrain(root, context, loop_counter); // remove any non-default optional dependencies purgeOptionalDependencies(root, context.result); // the root package is implied by the `root` argument and will not be // returned explicitly context.result.remove(rootbase); logDiagnostic("Dependency resolution result:"); foreach (d; context.result.keys.sort()) logDiagnostic(" %s: %s", d, context.result[d]); return context.result; } protected abstract CONFIG[] getAllConfigs(string pack); protected abstract CONFIG[] getSpecificConfigs(string pack, TreeNodes nodes); protected abstract TreeNodes[] getChildren(TreeNode node); protected abstract bool matches(CONFIGS configs, CONFIG config); private static struct ResolveConfig { CONFIG config; bool included; } private static struct ResolveContext { /** Contains all packages visited by the resolution process so far. The key is the qualified name of the package (base + sub) */ void[0][string] visited; /// The finally chosen configurations for each package CONFIG[string] result; /// The set of available configurations for each package ResolveConfig[][string] configs; /// Determines if a certain package has already been processed bool isVisited(string package_) const { return (package_ in visited) !is null; } /// Marks a package as processed void setVisited(string package_) { visited[package_] = (void[0]).init; } /// Returns a deep clone ResolveContext clone() { ResolveContext ret; ret.visited = this.visited.dup; ret.result = this.result.dup; foreach (pack, cfgs; this.configs) { ret.configs[pack] = cfgs.dup; } return ret; } } /** Starting with a single node, fills `context` with a minimized set of configurations that form valid solutions. */ private void constrain(TreeNode n, ref ResolveContext context, ref long max_iterations) { auto base = n.pack.basePackageName; assert(base in context.configs); if (context.isVisited(n.pack)) return; context.setVisited(n.pack); context.result[base] = n.config; foreach (j, ref sc; context.configs[base]) sc.included = sc.config == n.config; auto dependencies = getChildren(n); foreach (dep; dependencies) { // lazily load all dependency configurations auto depbase = dep.pack.basePackageName; auto di = depbase in context.configs; if (!di) { context.configs[depbase] = getAllConfigs(depbase) .map!(c => ResolveConfig(c, true)) .array; di = depbase in context.configs; } // add any dependee defined dependency configurations foreach (sc; getSpecificConfigs(n.pack, dep)) if (!(*di).canFind!(c => c.config == sc)) *di = ResolveConfig(sc, true) ~ *di; // restrain the configurations to the current dependency spec bool any_config = false; foreach (i, ref c; *di) if (c.included) { if (!matches(dep.configs, c.config)) c.included = false; else any_config = true; } if (!any_config && dep.depType == DependencyType.required) { if ((*di).length) throw new ResolveException(n, dep, context); else throw new DependencyLoadException(n, dep); } } constrainDependencies(n, dependencies, 0, context, max_iterations); } /** Recurses back into `constrain` while recursively going through `n`'s dependencies. This attempts to constrain each dependency, while keeping each of them in a nested stack frame. This allows any errors to properly back propagate. */ private void constrainDependencies(TreeNode n, TreeNodes[] dependencies, size_t depidx, ref ResolveContext context, ref long max_iterations) { if (depidx >= dependencies.length) return; assert (--max_iterations > 0, "The dependency resolution process is taking too long. The" ~ " dependency graph is likely hitting a pathological case in" ~ " the resolution algorithm. Please file a bug report at" ~ " https://github.com/dlang/dub/issues and mention the package" ~ " recipe that reproduces this error."); auto dep = &dependencies[depidx]; auto depbase = dep.pack.basePackageName; auto depconfigs = context.configs[depbase]; Exception first_err; // try each configuration/version of the current dependency foreach (i, c; depconfigs) { if (c.included) { try { // try the configuration on a cloned context auto subcontext = context.clone; constrain(TreeNode(dep.pack, c.config), subcontext, max_iterations); constrainDependencies(n, dependencies, depidx+1, subcontext, max_iterations); // if a branch succeeded, replace the current context // with the one from the branch and return context = subcontext; return; } catch (Exception e) { if (!first_err) first_err = e; } } } // ignore unsatisfiable optional dependencies if (dep.depType != DependencyType.required) { auto subcontext = context.clone; constrainDependencies(n, dependencies, depidx+1, subcontext, max_iterations); context = subcontext; return; } // report the first error encountered to the user if (first_err) throw first_err; // should have thrown in constrainRec before reaching this assert(false, format("Got no configuration for dependency %s %s of %s %s!?", dep.pack, dep.configs, n.pack, n.config)); } private void purgeOptionalDependencies(TreeNode root, ref CONFIG[string] configs) { bool[string] required; bool[string] visited; void markRecursively(TreeNode node) { if (node.pack in visited) return; visited[node.pack] = true; required[node.pack.basePackageName] = true; foreach (dep; getChildren(node).filter!(dep => dep.depType != DependencyType.optional)) if (auto dp = dep.pack.basePackageName in configs) markRecursively(TreeNode(dep.pack, *dp)); } // recursively mark all required dependencies of the concrete dependency tree markRecursively(root); // remove all un-marked configurations foreach (p; configs.keys.dup) if (p !in required) configs.remove(p); } final class ResolveException : Exception { import std.range : chain, only; import std.typecons : tuple; string failedNode; this(TreeNode parent, TreeNodes dep, in ref ResolveContext context, string file = __FILE__, size_t line = __LINE__) { auto m = format("Unresolvable dependencies to package %s:", dep.pack.basePackageName); super(m, file, line); this.failedNode = dep.pack; auto failbase = failedNode.basePackageName; // get the list of all dependencies to the failed package auto deps = context.visited.byKey .filter!(p => p.basePackageName in context.result) .map!(p => TreeNode(p, context.result[p.basePackageName])) .map!(n => getChildren(n) .filter!(d => d.pack.basePackageName == failbase) .map!(d => tuple(n, d)) ) .join .sort!((a, b) => a[0].pack < b[0].pack); foreach (d; deps) { // filter out trivial self-dependencies if (d[0].pack.basePackageName == failbase && matches(d[1].configs, d[0].config)) continue; msg ~= format("\n %s %s depends on %s %s", d[0].pack, d[0].config, d[1].pack, d[1].configs); } } } final class DependencyLoadException : Exception { TreeNode parent; TreeNodes dependency; this(TreeNode parent, TreeNodes dep) { auto m = format("Failed to find any versions for package %s, referenced by %s %s", dep.pack, parent.pack, parent.config); super(m, file, line); this.parent = parent; this.dependency = dep; } } } enum DependencyType { required, optionalDefault, optional } private string basePackageName(string p) { import std.algorithm.searching : findSplit; return p.findSplit(":")[0]; } unittest { static struct IntConfig { int value; alias value this; enum invalid = IntConfig(-1); } static IntConfig ic(int v) { return IntConfig(v); } static struct IntConfigs { IntConfig[] configs; alias configs this; } static IntConfigs ics(IntConfig[] cfgs) { return IntConfigs(cfgs); } static class TestResolver : DependencyResolver!(IntConfigs, IntConfig) { private TreeNodes[][string] m_children; this(TreeNodes[][string] children) { m_children = children; } protected override IntConfig[] getAllConfigs(string pack) { auto ret = appender!(IntConfig[]); foreach (p; m_children.byKey) { if (p.length <= pack.length+1) continue; if (p[0 .. pack.length] != pack || p[pack.length] != ':') continue; auto didx = p.lastIndexOf(':'); ret ~= ic(p[didx+1 .. $].to!uint); } ret.data.sort!"a>b"(); return ret.data; } protected override IntConfig[] getSpecificConfigs(string pack, TreeNodes nodes) { return null; } protected override TreeNodes[] getChildren(TreeNode node) { return m_children.get(node.pack ~ ":" ~ node.config.to!string(), null); } protected override bool matches(IntConfigs configs, IntConfig config) { return configs.canFind(config); } } // properly back up if conflicts are detected along the way (d:2 vs d:1) with (TestResolver) { auto res = new TestResolver([ "a:0": [TreeNodes("b", ics([ic(2), ic(1)])), TreeNodes("d", ics([ic(1)])), TreeNodes("e", ics([ic(2), ic(1)]))], "b:1": [TreeNodes("c", ics([ic(2), ic(1)])), TreeNodes("d", ics([ic(1)]))], "b:2": [TreeNodes("c", ics([ic(3), ic(2)])), TreeNodes("d", ics([ic(2), ic(1)]))], "c:1": [], "c:2": [], "c:3": [], "d:1": [], "d:2": [], "e:1": [], "e:2": [], ]); assert(res.resolve(TreeNode("a", ic(0))) == ["b":ic(2), "c":ic(3), "d":ic(1), "e":ic(2)], format("%s", res.resolve(TreeNode("a", ic(0))))); } // handle cyclic dependencies gracefully with (TestResolver) { auto res = new TestResolver([ "a:0": [TreeNodes("b", ics([ic(1)]))], "b:1": [TreeNodes("b", ics([ic(1)]))] ]); assert(res.resolve(TreeNode("a", ic(0))) == ["b":ic(1)]); } // don't choose optional dependencies by default with (TestResolver) { auto res = new TestResolver([ "a:0": [TreeNodes("b", ics([ic(1)]), DependencyType.optional)], "b:1": [] ]); assert(res.resolve(TreeNode("a", ic(0))).length == 0, to!string(res.resolve(TreeNode("a", ic(0))))); } // choose default optional dependencies by default with (TestResolver) { auto res = new TestResolver([ "a:0": [TreeNodes("b", ics([ic(1)]), DependencyType.optionalDefault)], "b:1": [] ]); assert(res.resolve(TreeNode("a", ic(0))) == ["b":ic(1)], to!string(res.resolve(TreeNode("a", ic(0))))); } // choose optional dependency if non-optional within the dependency tree with (TestResolver) { auto res = new TestResolver([ "a:0": [TreeNodes("b", ics([ic(1)]), DependencyType.optional), TreeNodes("c", ics([ic(1)]))], "b:1": [], "c:1": [TreeNodes("b", ics([ic(1)]))] ]); assert(res.resolve(TreeNode("a", ic(0))) == ["b":ic(1), "c":ic(1)], to!string(res.resolve(TreeNode("a", ic(0))))); } // don't choose optional dependency if non-optional outside of final dependency tree with (TestResolver) { auto res = new TestResolver([ "a:0": [TreeNodes("b", ics([ic(1)]), DependencyType.optional)], "b:1": [], "preset:0": [TreeNodes("b", ics([ic(1)]))] ]); assert(res.resolve(TreeNode("a", ic(0))).length == 0, to!string(res.resolve(TreeNode("a", ic(0))))); } // don't choose optional dependency if non-optional in a non-selected version with (TestResolver) { auto res = new TestResolver([ "a:0": [TreeNodes("b", ics([ic(1), ic(2)]))], "b:1": [TreeNodes("c", ics([ic(1)]))], "b:2": [TreeNodes("c", ics([ic(1)]), DependencyType.optional)], "c:1": [] ]); assert(res.resolve(TreeNode("a", ic(0))) == ["b":ic(2)], to!string(res.resolve(TreeNode("a", ic(0))))); } // make sure non-satisfiable dependencies are not a problem, even if non-optional in some dependencies with (TestResolver) { auto res = new TestResolver([ "a:0": [TreeNodes("b", ics([ic(1), ic(2)]))], "b:1": [TreeNodes("c", ics([ic(2)]))], "b:2": [TreeNodes("c", ics([ic(2)]), DependencyType.optional)], "c:1": [] ]); assert(res.resolve(TreeNode("a", ic(0))) == ["b":ic(2)], to!string(res.resolve(TreeNode("a", ic(0))))); } // check error message for multiple conflicting dependencies with (TestResolver) { auto res = new TestResolver([ "a:0": [TreeNodes("b", ics([ic(1)])), TreeNodes("c", ics([ic(1)]))], "b:1": [TreeNodes("d", ics([ic(1)]))], "c:1": [TreeNodes("d", ics([ic(2)]))], "d:1": [], "d:2": [] ]); try { res.resolve(TreeNode("a", ic(0))); assert(false, "Expected resolve to throw."); } catch (ResolveException e) { assert(e.msg == "Unresolvable dependencies to package d:" ~ "\n b 1 depends on d [1]" ~ "\n c 1 depends on d [2]"); } } // check error message for invalid dependency with (TestResolver) { auto res = new TestResolver([ "a:0": [TreeNodes("b", ics([ic(1)]))] ]); try { res.resolve(TreeNode("a", ic(0))); assert(false, "Expected resolve to throw."); } catch (DependencyLoadException e) { assert(e.msg == "Failed to find any versions for package b, referenced by a 0"); } } // regression: unresolvable optional dependency skips the remaining dependencies with (TestResolver) { auto res = new TestResolver([ "a:0": [ TreeNodes("b", ics([ic(2)]), DependencyType.optional), TreeNodes("c", ics([ic(1)])) ], "b:1": [], "c:1": [] ]); assert(res.resolve(TreeNode("a", ic(0))) == ["c":ic(1)]); } } dub-1.19.0/source/dub/description.d000066400000000000000000000124761360435400500171300ustar00rootroot00000000000000/** Types for project descriptions (dub describe). Copyright: © 2015-2016 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.description; import dub.compilers.buildsettings; import dub.dependency; import dub.internal.vibecompat.data.serialization; /** Describes a complete project for use in IDEs or build tools. The build settings will be specific to the compiler, platform and configuration that has been selected. */ struct ProjectDescription { string rootPackage; /// Name of the root package being built string configuration; /// Name of the selected build configuration string buildType; /// Name of the selected build type string compiler; /// Canonical name of the compiler used (e.g. "dmd", "gdc" or "ldc") string[] architecture; /// Architecture constants for the selected platform (e.g. `["x86_64"]`) string[] platform; /// Platform constants for the selected platform (e.g. `["posix", "osx"]`) PackageDescription[] packages; /// All packages in the dependency tree TargetDescription[] targets; /// Build targets @ignore size_t[string] targetLookup; /// Target index by package name name /// Targets by name ref inout(TargetDescription) lookupTarget(string name) inout { import std.exception : enforce; auto pti = name in targetLookup; enforce(pti !is null, "Target '"~name~"' doesn't exist. Is the target type set to \"none\" in the package recipe?"); return targets[*pti]; } /// Projects by name ref inout(PackageDescription) lookupPackage(string name) inout { foreach (ref p; packages) if (p.name == name) { return p; } throw new Exception("Package '"~name~"' not found in dependency tree."); } /// Root package ref inout(PackageDescription) lookupRootPackage() inout { return lookupPackage(rootPackage); } } /** Describes the build settings and meta data of a single package. This structure contains the effective build settings and dependencies for the selected build platform. This structure is most useful for displaying information about a package in an IDE. Use `TargetDescription` instead when writing a build-tool. */ struct PackageDescription { string path; /// Path to the package string name; /// Qualified name of the package Version version_; /// Version of the package string description; string homepage; string[] authors; string copyright; string license; string[] dependencies; bool active; /// Does this package take part in the build? string configuration; /// The configuration that is built @byName TargetType targetType; string targetPath; string targetName; string targetFileName; string workingDirectory; string mainSourceFile; string[] dflags; /// Flags passed to the D compiler string[] lflags; /// Flags passed to the linker string[] libs; /// Librariy names to link against (typically using "-l") string[] copyFiles; /// Files to copy to the target directory string[] extraDependencyFiles; /// Files to check for rebuild dub project string[] versions; /// D version identifiers to set string[] debugVersions; /// D debug version identifiers to set string[] importPaths; string[] stringImportPaths; string[] preGenerateCommands; /// commands executed before creating the description string[] postGenerateCommands; /// commands executed after creating the description string[] preBuildCommands; /// Commands to execute prior to every build string[] postBuildCommands; /// Commands to execute after every build string[] preRunCommands; /// Commands to execute prior to every run string[] postRunCommands; /// Commands to execute after every run @byName BuildRequirement[] buildRequirements; @byName BuildOption[] options; SourceFileDescription[] files; /// A list of all source/import files possibly used by the package } /** Describes the settings necessary to build a certain binary target. */ struct TargetDescription { string rootPackage; /// Main package associated with this target, this is also the name of the target. string[] packages; /// All packages contained in this target (e.g. for target type "sourceLibrary") string rootConfiguration; /// Build configuration of the target's root package used for building BuildSettings buildSettings; /// Final build settings to use when building the target string[] dependencies; /// List of all dependencies of this target (package names) string[] linkDependencies; /// List of all link-dependencies of this target (target names) } /** Description for a single source file known to the package. */ struct SourceFileDescription { @byName SourceFileRole role; /// Main role this file plays in the build process string path; /// Full path to the file } /** Determines the role that a file plays in the build process. If a file has multiple roles, higher enum values will have precedence, i.e. if a file is used both, as a source file and as an import file, it will be classified as a source file. */ enum SourceFileRole { unusedStringImport, /// Used as a string import for another configuration/platform unusedImport, /// Used as an import for another configuration/platform unusedSource, /// Used as a source file for another configuration/platform stringImport, /// Used as a string import file import_, /// Used as an import file source /// Used as a source file } dub-1.19.0/source/dub/dub.d000066400000000000000000001754531360435400500153640ustar00rootroot00000000000000/** A package manager. Copyright: © 2012-2013 Matthias Dondorff, 2012-2016 Sönke Ludwig License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Matthias Dondorff, Sönke Ludwig */ module dub.dub; import dub.compilers.compiler; import dub.dependency; import dub.dependencyresolver; import dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.url; import dub.package_; import dub.packagemanager; import dub.packagesuppliers; import dub.project; import dub.generators.generator; import dub.init; import std.algorithm; import std.array : array, replace; import std.conv : to; import std.exception : enforce; import std.file; import std.process : environment; import std.range : assumeSorted, empty; import std.string; import std.encoding : sanitize; // Set output path and options for coverage reports version (DigitalMars) version (D_Coverage) { shared static this() { import core.runtime, std.file, std.path, std.stdio; dmd_coverSetMerge(true); auto path = buildPath(dirName(thisExePath()), "../cov"); if (!path.exists) mkdir(path); dmd_coverDestPath(path); } } static this() { import dub.compilers.dmd : DMDCompiler; import dub.compilers.gdc : GDCCompiler; import dub.compilers.ldc : LDCCompiler; registerCompiler(new DMDCompiler); registerCompiler(new GDCCompiler); registerCompiler(new LDCCompiler); } deprecated("use defaultRegistryURLs") enum defaultRegistryURL = defaultRegistryURLs[0]; /// The URL to the official package registry and it's default fallback registries. static immutable string[] defaultRegistryURLs = [ "https://code.dlang.org/", "https://code-mirror.dlang.io/", "https://dub-registry.herokuapp.com/", ]; /** Returns a default list of package suppliers. This will contain a single package supplier that points to the official package registry. See_Also: `defaultRegistryURLs` */ PackageSupplier[] defaultPackageSuppliers() { logDiagnostic("Using dub registry url '%s'", defaultRegistryURLs[0]); return [new FallbackPackageSupplier(defaultRegistryURLs.map!getRegistryPackageSupplier.array)]; } /** Returns a registry package supplier according to protocol. Allowed protocols are dub+http(s):// and maven+http(s)://. */ PackageSupplier getRegistryPackageSupplier(string url) { switch (url.startsWith("dub+", "mvn+", "file://")) { case 1: return new RegistryPackageSupplier(URL(url[4..$])); case 2: return new MavenRegistryPackageSupplier(URL(url[4..$])); case 3: return new FileSystemPackageSupplier(NativePath(url[7..$])); default: return new RegistryPackageSupplier(URL(url)); } } unittest { auto dubRegistryPackageSupplier = getRegistryPackageSupplier("dub+https://code.dlang.org"); assert(dubRegistryPackageSupplier.description.canFind(" https://code.dlang.org")); dubRegistryPackageSupplier = getRegistryPackageSupplier("https://code.dlang.org"); assert(dubRegistryPackageSupplier.description.canFind(" https://code.dlang.org")); auto mavenRegistryPackageSupplier = getRegistryPackageSupplier("mvn+http://localhost:8040/maven/libs-release/dubpackages"); assert(mavenRegistryPackageSupplier.description.canFind(" http://localhost:8040/maven/libs-release/dubpackages")); auto fileSystemPackageSupplier = getRegistryPackageSupplier("file:///etc/dubpackages"); assert(fileSystemPackageSupplier.description.canFind(" " ~ NativePath("/etc/dubpackages").toNativeString)); } /** Provides a high-level entry point for DUB's functionality. This class provides means to load a certain project (a root package with all of its dependencies) and to perform high-level operations as found in the command line interface. */ class Dub { private { bool m_dryRun = false; PackageManager m_packageManager; PackageSupplier[] m_packageSuppliers; NativePath m_rootPath; SpecialDirs m_dirs; DubConfig m_config; NativePath m_projectPath; Project m_project; NativePath m_overrideSearchPath; string m_defaultCompiler; string m_defaultArchitecture; } /** The default placement location of fetched packages. This property can be altered, so that packages which are downloaded as part of the normal upgrade process are stored in a certain location. This is how the "--local" and "--system" command line switches operate. */ PlacementLocation defaultPlacementLocation = PlacementLocation.user; /** Initializes the instance for use with a specific root package. Note that a package still has to be loaded using one of the `loadPackage` overloads. Params: root_path = Path to the root package additional_package_suppliers = A list of package suppliers to try before the suppliers found in the configurations files and the `defaultPackageSuppliers`. skip_registry = Can be used to skip using the configured package suppliers, as well as the default suppliers. */ this(string root_path = ".", PackageSupplier[] additional_package_suppliers = null, SkipPackageSuppliers skip_registry = SkipPackageSuppliers.none) { m_rootPath = NativePath(root_path); if (!m_rootPath.absolute) m_rootPath = NativePath(getcwd()) ~ m_rootPath; init(m_rootPath); if (skip_registry == SkipPackageSuppliers.none) m_packageSuppliers = getPackageSuppliers(additional_package_suppliers); else m_packageSuppliers = getPackageSuppliers(additional_package_suppliers, skip_registry); m_packageManager = new PackageManager(m_rootPath, m_dirs.localRepository, m_dirs.systemSettings); auto ccps = m_config.customCachePaths; if (ccps.length) m_packageManager.customCachePaths = ccps; updatePackageSearchPath(); } unittest { scope (exit) environment.remove("DUB_REGISTRY"); auto dub = new Dub(".", null, SkipPackageSuppliers.configured); assert(dub.m_packageSuppliers.length == 0); environment["DUB_REGISTRY"] = "http://example.com/"; dub = new Dub(".", null, SkipPackageSuppliers.configured); assert(dub.m_packageSuppliers.length == 1); environment["DUB_REGISTRY"] = "http://example.com/;http://foo.com/"; dub = new Dub(".", null, SkipPackageSuppliers.configured); assert(dub.m_packageSuppliers.length == 2); dub = new Dub(".", [new RegistryPackageSupplier(URL("http://bar.com/"))], SkipPackageSuppliers.configured); assert(dub.m_packageSuppliers.length == 3); } /** Get the list of package suppliers. Params: additional_package_suppliers = A list of package suppliers to try before the suppliers found in the configurations files and the `defaultPackageSuppliers`. skip_registry = Can be used to skip using the configured package suppliers, as well as the default suppliers. */ public PackageSupplier[] getPackageSuppliers(PackageSupplier[] additional_package_suppliers, SkipPackageSuppliers skip_registry) { PackageSupplier[] ps = additional_package_suppliers; if (skip_registry < SkipPackageSuppliers.all) { ps ~= environment.get("DUB_REGISTRY", null) .splitter(";") .map!(url => getRegistryPackageSupplier(url)) .array; } if (skip_registry < SkipPackageSuppliers.configured) { ps ~= m_config.registryURLs .map!(url => getRegistryPackageSupplier(url)) .array; } if (skip_registry < SkipPackageSuppliers.standard) ps ~= defaultPackageSuppliers(); return ps; } /// ditto public PackageSupplier[] getPackageSuppliers(PackageSupplier[] additional_package_suppliers) { return getPackageSuppliers(additional_package_suppliers, m_config.skipRegistry); } unittest { scope (exit) environment.remove("DUB_REGISTRY"); auto dub = new Dub(".", null, SkipPackageSuppliers.none); dub.m_config = new DubConfig(Json(["skipRegistry": Json("none")]), null); assert(dub.getPackageSuppliers(null).length == 1); dub.m_config = new DubConfig(Json(["skipRegistry": Json("configured")]), null); assert(dub.getPackageSuppliers(null).length == 0); dub.m_config = new DubConfig(Json(["skipRegistry": Json("standard")]), null); assert(dub.getPackageSuppliers(null).length == 0); environment["DUB_REGISTRY"] = "http://example.com/"; assert(dub.getPackageSuppliers(null).length == 1); } /** Initializes the instance with a single package search path, without loading a package. This constructor corresponds to the "--bare" option of the command line interface. Use */ this(NativePath override_path) { init(NativePath()); m_overrideSearchPath = override_path; m_packageManager = new PackageManager(NativePath(), NativePath(), NativePath(), false); updatePackageSearchPath(); } private void init(NativePath root_path) { import std.file : tempDir; version(Windows) { m_dirs.systemSettings = NativePath(environment.get("ProgramData")) ~ "dub/"; immutable appDataDir = environment.get("APPDATA"); m_dirs.userSettings = NativePath(appDataDir) ~ "dub/"; m_dirs.localRepository = NativePath(environment.get("LOCALAPPDATA", appDataDir)) ~ "dub"; migrateRepositoryFromRoaming(m_dirs.userSettings ~"\\packages", m_dirs.localRepository ~ "\\packages"); } else version(Posix){ m_dirs.systemSettings = NativePath("/var/lib/dub/"); m_dirs.userSettings = NativePath(environment.get("HOME")) ~ ".dub/"; if (!m_dirs.userSettings.absolute) m_dirs.userSettings = NativePath(getcwd()) ~ m_dirs.userSettings; m_dirs.localRepository = m_dirs.userSettings; } m_dirs.temp = NativePath(tempDir); m_config = new DubConfig(jsonFromFile(m_dirs.systemSettings ~ "settings.json", true), m_config); m_config = new DubConfig(jsonFromFile(NativePath(thisExePath).parentPath ~ "../etc/dub/settings.json", true), m_config); m_config = new DubConfig(jsonFromFile(m_dirs.userSettings ~ "settings.json", true), m_config); if (!root_path.empty) m_config = new DubConfig(jsonFromFile(root_path ~ "dub.settings.json", true), m_config); determineDefaultCompiler(); m_defaultArchitecture = m_config.defaultArchitecture; } version(Windows) private void migrateRepositoryFromRoaming(NativePath roamingDir, NativePath localDir) { immutable roamingDirPath = roamingDir.toNativeString(); if (!existsDirectory(roamingDir)) return; immutable localDirPath = localDir.toNativeString(); logInfo("Detected a package cache in " ~ roamingDirPath ~ ". This will be migrated to " ~ localDirPath ~ ". Please wait..."); if (!existsDirectory(localDir)) { mkdirRecurse(localDirPath); } runCommand(`xcopy /s /e /y "` ~ roamingDirPath ~ `" "` ~ localDirPath ~ `" > NUL`); rmdirRecurse(roamingDirPath); } @property void dryRun(bool v) { m_dryRun = v; } /** Returns the root path (usually the current working directory). */ @property NativePath rootPath() const { return m_rootPath; } /// ditto @property void rootPath(NativePath root_path) { m_rootPath = root_path; if (!m_rootPath.absolute) m_rootPath = NativePath(getcwd()) ~ m_rootPath; } /// Returns the name listed in the dub.json of the current /// application. @property string projectName() const { return m_project.name; } @property NativePath projectPath() const { return m_projectPath; } @property string[] configurations() const { return m_project.configurations; } @property inout(PackageManager) packageManager() inout { return m_packageManager; } @property inout(Project) project() inout { return m_project; } /** Returns the default compiler binary to use for building D code. If set, the "defaultCompiler" field of the DUB user or system configuration file will be used. Otherwise the PATH environment variable will be searched for files named "dmd", "gdc", "gdmd", "ldc2", "ldmd2" (in that order, taking into account operating system specific file extensions) and the first match is returned. If no match is found, "dmd" will be used. */ @property string defaultCompiler() const { return m_defaultCompiler; } /** Returns the default architecture to use for building D code. If set, the "defaultArchitecture" field of the DUB user or system configuration file will be used. Otherwise null will be returned. */ @property string defaultArchitecture() const { return m_defaultArchitecture; } /** Loads the package that resides within the configured `rootPath`. */ void loadPackage() { loadPackage(m_rootPath); } /// Loads the package from the specified path as the main project package. void loadPackage(NativePath path) { m_projectPath = path; updatePackageSearchPath(); m_project = new Project(m_packageManager, m_projectPath); } /// Loads a specific package as the main project package (can be a sub package) void loadPackage(Package pack) { m_projectPath = pack.path; updatePackageSearchPath(); m_project = new Project(m_packageManager, pack); } /** Loads a single file package. Single-file packages are D files that contain a package receipe comment at their top. A recipe comment must be a nested `/+ ... +/` style comment, containing the virtual recipe file name and a colon, followed by the recipe contents (what would normally be in dub.sdl/dub.json). Example: --- /+ dub.sdl: name "test" dependency "vibe-d" version="~>0.7.29" +/ import vibe.http.server; void main() { auto settings = new HTTPServerSettings; settings.port = 8080; listenHTTP(settings, &hello); } void hello(HTTPServerRequest req, HTTPServerResponse res) { res.writeBody("Hello, World!"); } --- The script above can be invoked with "dub --single test.d". */ void loadSingleFilePackage(NativePath path) { import dub.recipe.io : parsePackageRecipe; import std.file : mkdirRecurse, readText; import std.path : baseName, stripExtension; path = makeAbsolute(path); string file_content = readText(path.toNativeString()); if (file_content.startsWith("#!")) { auto idx = file_content.indexOf('\n'); enforce(idx > 0, "The source fine doesn't contain anything but a shebang line."); file_content = file_content[idx+1 .. $]; } file_content = file_content.strip(); string recipe_content; if (file_content.startsWith("/+")) { file_content = file_content[2 .. $]; auto idx = file_content.indexOf("+/"); enforce(idx >= 0, "Missing \"+/\" to close comment."); recipe_content = file_content[0 .. idx].strip(); } else throw new Exception("The source file must start with a recipe comment."); auto nidx = recipe_content.indexOf('\n'); auto idx = recipe_content.indexOf(':'); enforce(idx > 0 && (nidx < 0 || nidx > idx), "The first line of the recipe comment must list the recipe file name followed by a colon (e.g. \"/+ dub.sdl:\")."); auto recipe_filename = recipe_content[0 .. idx]; recipe_content = recipe_content[idx+1 .. $]; auto recipe_default_package_name = path.toString.baseName.stripExtension.strip; auto recipe = parsePackageRecipe(recipe_content, recipe_filename, null, recipe_default_package_name); enforce(recipe.buildSettings.sourceFiles.length == 0, "Single-file packages are not allowed to specify source files."); enforce(recipe.buildSettings.sourcePaths.length == 0, "Single-file packages are not allowed to specify source paths."); enforce(recipe.buildSettings.importPaths.length == 0, "Single-file packages are not allowed to specify import paths."); recipe.buildSettings.sourceFiles[""] = [path.toNativeString()]; recipe.buildSettings.sourcePaths[""] = []; recipe.buildSettings.importPaths[""] = []; recipe.buildSettings.mainSourceFile = path.toNativeString(); if (recipe.buildSettings.targetType == TargetType.autodetect) recipe.buildSettings.targetType = TargetType.executable; auto pack = new Package(recipe, path.parentPath, null, "~master"); loadPackage(pack); } /// ditto void loadSingleFilePackage(string path) { loadSingleFilePackage(NativePath(path)); } /** Disables the default search paths and only searches a specific directory for packages. */ void overrideSearchPath(NativePath path) { if (!path.absolute) path = NativePath(getcwd()) ~ path; m_overrideSearchPath = path; updatePackageSearchPath(); } /** Gets the default configuration for a particular build platform. This forwards to `Project.getDefaultConfiguration` and requires a project to be loaded. */ string getDefaultConfiguration(BuildPlatform platform, bool allow_non_library_configs = true) const { return m_project.getDefaultConfiguration(platform, allow_non_library_configs); } /** Attempts to upgrade the dependency selection of the loaded project. Params: options = Flags that control how the upgrade is carried out packages_to_upgrade = Optional list of packages. If this list contains one or more packages, only those packages will be upgraded. Otherwise, all packages will be upgraded at once. */ void upgrade(UpgradeOptions options, string[] packages_to_upgrade = null) { // clear non-existent version selections if (!(options & UpgradeOptions.upgrade)) { next_pack: foreach (p; m_project.selections.selectedPackages) { auto dep = m_project.selections.getSelectedVersion(p); if (!dep.path.empty) { auto path = dep.path; if (!path.absolute) path = this.rootPath ~ path; try if (m_packageManager.getOrLoadPackage(path)) continue; catch (Exception e) { logDebug("Failed to load path based selection: %s", e.toString().sanitize); } } else { if (m_packageManager.getPackage(p, dep.version_)) continue; foreach (ps; m_packageSuppliers) { try { auto versions = ps.getVersions(p); if (versions.canFind!(v => dep.matches(v))) continue next_pack; } catch (Exception e) { logWarn("Error querying versions for %s, %s: %s", p, ps.description, e.msg); logDebug("Full error: %s", e.toString().sanitize()); } } } logWarn("Selected package %s %s doesn't exist. Using latest matching version instead.", p, dep); m_project.selections.deselectVersion(p); } } Dependency[string] versions; auto resolver = new DependencyVersionResolver(this, options); foreach (p; packages_to_upgrade) resolver.addPackageToUpgrade(p); versions = resolver.resolve(m_project.rootPackage, m_project.selections); if (options & UpgradeOptions.dryRun) { bool any = false; string rootbasename = getBasePackageName(m_project.rootPackage.name); foreach (p, ver; versions) { if (!ver.path.empty) continue; auto basename = getBasePackageName(p); if (basename == rootbasename) continue; if (!m_project.selections.hasSelectedVersion(basename)) { logInfo("Package %s would be selected with version %s.", basename, ver); any = true; continue; } auto sver = m_project.selections.getSelectedVersion(basename); if (!sver.path.empty) continue; if (ver.version_ <= sver.version_) continue; logInfo("Package %s would be upgraded from %s to %s.", basename, sver, ver); any = true; } if (any) logInfo("Use \"dub upgrade\" to perform those changes."); return; } foreach (p; versions.byKey) { auto ver = versions[p]; // Workaround for DMD 2.070.0 AA issue (crashes in aaApply2 if iterating by key+value) assert(!p.canFind(":"), "Resolved packages contain a sub package!?: "~p); Package pack; if (!ver.path.empty) { try pack = m_packageManager.getOrLoadPackage(ver.path); catch (Exception e) { logDebug("Failed to load path based selection: %s", e.toString().sanitize); continue; } } else { pack = m_packageManager.getBestPackage(p, ver); if (pack && m_packageManager.isManagedPackage(pack) && ver.version_.isBranch && (options & UpgradeOptions.upgrade) != 0) { // TODO: only re-install if there is actually a new commit available logInfo("Re-installing branch based dependency %s %s", p, ver.toString()); m_packageManager.remove(pack); pack = null; } } FetchOptions fetchOpts; fetchOpts |= (options & UpgradeOptions.preRelease) != 0 ? FetchOptions.usePrerelease : FetchOptions.none; if (!pack) fetch(p, ver, defaultPlacementLocation, fetchOpts, "getting selected version"); if ((options & UpgradeOptions.select) && p != m_project.rootPackage.name) { if (ver.path.empty) m_project.selections.selectVersion(p, ver.version_); else { NativePath relpath = ver.path; if (relpath.absolute) relpath = relpath.relativeTo(m_project.rootPackage.path); m_project.selections.selectVersion(p, relpath); } } } string[] missingDependenciesBeforeReinit = m_project.missingDependencies; m_project.reinit(); if (!m_project.hasAllDependencies) { auto resolvedDependencies = setDifference( assumeSorted(missingDependenciesBeforeReinit), assumeSorted(m_project.missingDependencies) ); if (!resolvedDependencies.empty) upgrade(options, m_project.missingDependencies); } if ((options & UpgradeOptions.select) && !(options & (UpgradeOptions.noSaveSelections | UpgradeOptions.dryRun))) m_project.saveSelections(); } /** Generate project files for a specified generator. Any existing project files will be overridden. */ void generateProject(string ide, GeneratorSettings settings) { auto generator = createProjectGenerator(ide, m_project); if (m_dryRun) return; // TODO: pass m_dryRun to the generator generator.generate(settings); } /** Executes tests on the current project. Throws an exception, if unittests failed. */ void testProject(GeneratorSettings settings, string config, NativePath custom_main_file) { if (!custom_main_file.empty && !custom_main_file.absolute) custom_main_file = getWorkingDirectory() ~ custom_main_file; if (config.length == 0) { // if a custom main file was given, favor the first library configuration, so that it can be applied if (!custom_main_file.empty) config = m_project.getDefaultConfiguration(settings.platform, false); // else look for a "unittest" configuration if (!config.length && m_project.rootPackage.configurations.canFind("unittest")) config = "unittest"; // if not found, fall back to the first "library" configuration if (!config.length) config = m_project.getDefaultConfiguration(settings.platform, false); // if still nothing found, use the first executable configuration if (!config.length) config = m_project.getDefaultConfiguration(settings.platform, true); } auto generator = createProjectGenerator("build", m_project); auto test_config = format("%s-test-%s", m_project.rootPackage.name.replace(".", "-").replace(":", "-"), config); BuildSettings lbuildsettings = settings.buildSettings; m_project.addBuildSettings(lbuildsettings, settings, config, null, true); if (lbuildsettings.targetType == TargetType.none) { logInfo(`Configuration '%s' has target type "none". Skipping test.`, config); return; } if (lbuildsettings.targetType == TargetType.executable && config == "unittest") { logInfo("Running custom 'unittest' configuration.", config); if (!custom_main_file.empty) logWarn("Ignoring custom main file."); settings.config = config; } else if (lbuildsettings.sourceFiles.empty) { logInfo(`No source files found in configuration '%s'. Falling back to "dub -b unittest".`, config); if (!custom_main_file.empty) logWarn("Ignoring custom main file."); settings.config = m_project.getDefaultConfiguration(settings.platform); } else { import std.algorithm : remove; logInfo(`Generating test runner configuration '%s' for '%s' (%s).`, test_config, config, lbuildsettings.targetType); BuildSettingsTemplate tcinfo = m_project.rootPackage.recipe.getConfiguration(config).buildSettings; tcinfo.targetType = TargetType.executable; tcinfo.targetName = test_config; // HACK for vibe.d's legacy main() behavior: tcinfo.versions[""] ~= "VibeCustomMain"; m_project.rootPackage.recipe.buildSettings.versions[""] = m_project.rootPackage.recipe.buildSettings.versions.get("", null).remove!(v => v == "VibeDefaultMain"); // TODO: remove this ^ once vibe.d has removed the default main implementation auto mainfil = tcinfo.mainSourceFile; if (!mainfil.length) mainfil = m_project.rootPackage.recipe.buildSettings.mainSourceFile; string custommodname; if (!custom_main_file.empty) { import std.path; tcinfo.sourceFiles[""] ~= custom_main_file.relativeTo(m_project.rootPackage.path).toNativeString(); tcinfo.importPaths[""] ~= custom_main_file.parentPath.toNativeString(); custommodname = custom_main_file.head.name.baseName(".d"); } // prepare the list of tested modules string[] import_modules; foreach (file; lbuildsettings.sourceFiles) { if (file.endsWith(".d")) { auto fname = NativePath(file).head.name; if (NativePath(file).relativeTo(m_project.rootPackage.path) == NativePath(mainfil)) { logWarn("Excluding main source file %s from test.", mainfil); tcinfo.excludedSourceFiles[""] ~= mainfil; continue; } if (fname == "package.d") { logWarn("Excluding package.d file from test due to https://issues.dlang.org/show_bug.cgi?id=11847"); continue; } import_modules ~= dub.internal.utils.determineModuleName(lbuildsettings, NativePath(file), m_project.rootPackage.path); } } // generate main file NativePath mainfile = getTempFile("dub_test_root", ".d"); tcinfo.sourceFiles[""] ~= mainfile.toNativeString(); tcinfo.mainSourceFile = mainfile.toNativeString(); if (!m_dryRun) { auto fil = openFile(mainfile, FileMode.createTrunc); scope(exit) fil.close(); fil.write("module dub_test_root;\n"); fil.write("import std.typetuple;\n"); foreach (mod; import_modules) fil.write(format("static import %s;\n", mod)); fil.write("alias allModules = TypeTuple!("); foreach (i, mod; import_modules) { if (i > 0) fil.write(", "); fil.write(mod); } fil.write(");\n"); if (custommodname.length) { fil.write(format("import %s;\n", custommodname)); } else { fil.write(q{ import std.stdio; import core.runtime; void main() { writeln("All unit tests have been run successfully."); } shared static this() { version (Have_tested) { import tested; import core.runtime; import std.exception; Runtime.moduleUnitTester = () => true; //runUnitTests!app(new JsonTestResultWriter("results.json")); enforce(runUnitTests!allModules(new ConsoleTestResultWriter), "Unit tests failed."); } } }); } } m_project.rootPackage.recipe.configurations ~= ConfigurationInfo(test_config, tcinfo); m_project = new Project(m_packageManager, m_project.rootPackage); settings.config = test_config; } generator.generate(settings); } /** Executes D-Scanner tests on the current project. **/ void lintProject(string[] args) { import std.path : buildPath, buildNormalizedPath; if (m_dryRun) return; auto tool = "dscanner"; auto tool_pack = m_packageManager.getBestPackage(tool, ">=0.0.0"); if (!tool_pack) tool_pack = m_packageManager.getBestPackage(tool, "~master"); if (!tool_pack) { logInfo("%s is not present, getting and storing it user wide", tool); tool_pack = fetch(tool, Dependency(">=0.0.0"), defaultPlacementLocation, FetchOptions.none); } auto dscanner_dub = new Dub(null, m_packageSuppliers); dscanner_dub.loadPackage(tool_pack.path); dscanner_dub.upgrade(UpgradeOptions.select); auto compiler_binary = this.defaultCompiler; GeneratorSettings settings; settings.config = "application"; settings.compiler = getCompiler(compiler_binary); settings.platform = settings.compiler.determinePlatform(settings.buildSettings, compiler_binary, m_defaultArchitecture); settings.buildType = "debug"; settings.run = true; foreach (dependencyPackage; m_project.dependencies) { auto cfgs = m_project.getPackageConfigs(settings.platform, null, true); auto buildSettings = dependencyPackage.getBuildSettings(settings.platform, cfgs[dependencyPackage.name]); foreach (importPath; buildSettings.importPaths) { settings.runArgs ~= ["-I", buildNormalizedPath(dependencyPackage.path.toNativeString(), importPath.idup)]; } } string configFilePath = buildPath(m_project.rootPackage.path.toNativeString(), "dscanner.ini"); if (!args.canFind("--config") && exists(configFilePath)) { settings.runArgs ~= ["--config", configFilePath]; } settings.runArgs ~= args ~ [m_project.rootPackage.path.toNativeString()]; dscanner_dub.generateProject("build", settings); } /** Prints the specified build settings necessary for building the root package. */ void listProjectData(GeneratorSettings settings, string[] requestedData, ListBuildSettingsFormat list_type) { import std.stdio; import std.ascii : newline; // Split comma-separated lists string[] requestedDataSplit = requestedData .map!(a => a.splitter(",").map!strip) .joiner() .array(); auto data = m_project.listBuildSettings(settings, requestedDataSplit, list_type); string delimiter; final switch (list_type) with (ListBuildSettingsFormat) { case list: delimiter = newline ~ newline; break; case listNul: delimiter = "\0\0"; break; case commandLine: delimiter = " "; break; case commandLineNul: delimiter = "\0\0"; break; } write(data.joiner(delimiter)); if (delimiter != "\0\0") writeln(); } /// Cleans intermediate/cache files of the given package void cleanPackage(NativePath path) { logInfo("Cleaning package at %s...", path.toNativeString()); enforce(!Package.findPackageFile(path).empty, "No package found.", path.toNativeString()); // TODO: clear target files and copy files if (existsFile(path ~ ".dub/build")) rmdirRecurse((path ~ ".dub/build").toNativeString()); if (existsFile(path ~ ".dub/obj")) rmdirRecurse((path ~ ".dub/obj").toNativeString()); if (existsFile(path ~ ".dub/metadata_cache.json")) std.file.remove((path ~ ".dub/metadata_cache.json").toNativeString()); auto p = Package.load(path); if (p.getBuildSettings().targetType == TargetType.none) { foreach (sp; p.subPackages.filter!(sp => !sp.path.empty)) { cleanPackage(path ~ sp.path); } } } /// Fetches the package matching the dependency and places it in the specified location. Package fetch(string packageId, const Dependency dep, PlacementLocation location, FetchOptions options, string reason = "") { auto basePackageName = getBasePackageName(packageId); Json pinfo; PackageSupplier supplier; foreach(ps; m_packageSuppliers){ try { pinfo = ps.fetchPackageRecipe(basePackageName, dep, (options & FetchOptions.usePrerelease) != 0); if (pinfo.type == Json.Type.null_) continue; supplier = ps; break; } catch(Exception e) { logWarn("Package %s not found for %s: %s", packageId, ps.description, e.msg); logDebug("Full error: %s", e.toString().sanitize()); } } enforce(pinfo.type != Json.Type.undefined, "No package "~packageId~" was found matching the dependency "~dep.toString()); string ver = pinfo["version"].get!string; NativePath placement; final switch (location) { case PlacementLocation.local: placement = m_rootPath ~ ".dub/packages/"; break; case PlacementLocation.user: placement = m_dirs.localRepository ~ "packages/"; break; case PlacementLocation.system: placement = m_dirs.systemSettings ~ "packages/"; break; } // always upgrade branch based versions - TODO: actually check if there is a new commit available Package existing; try existing = m_packageManager.getPackage(packageId, ver, placement); catch (Exception e) { logWarn("Failed to load existing package %s: %s", ver, e.msg); logDiagnostic("Full error: %s", e.toString().sanitize); } if (options & FetchOptions.printOnly) { if (existing && existing.version_ != Version(ver)) logInfo("A new version for %s is available (%s -> %s). Run \"dub upgrade %s\" to switch.", packageId, existing.version_, ver, packageId); return null; } if (existing) { if (!ver.startsWith("~") || !(options & FetchOptions.forceBranchUpgrade) || location == PlacementLocation.local) { // TODO: support git working trees by performing a "git pull" instead of this logDiagnostic("Package %s %s (%s) is already present with the latest version, skipping upgrade.", packageId, ver, placement); return existing; } else { logInfo("Removing %s %s to prepare replacement with a new version.", packageId, ver); if (!m_dryRun) m_packageManager.remove(existing); } } if (reason.length) logInfo("Fetching %s %s (%s)...", packageId, ver, reason); else logInfo("Fetching %s %s...", packageId, ver); if (m_dryRun) return null; logDebug("Acquiring package zip file"); auto clean_package_version = ver[ver.startsWith("~") ? 1 : 0 .. $]; clean_package_version = clean_package_version.replace("+", "_"); // + has special meaning for Optlink if (!placement.existsFile()) mkdirRecurse(placement.toNativeString()); NativePath dstpath = placement ~ (basePackageName ~ "-" ~ clean_package_version); if (!dstpath.existsFile()) mkdirRecurse(dstpath.toNativeString()); // Support libraries typically used with git submodules like ae. // Such libraries need to have ".." as import path but this can create // import path leakage. dstpath = dstpath ~ basePackageName; import std.datetime : seconds; auto lock = lockFile(dstpath.toNativeString() ~ ".lock", 30.seconds); // possibly wait for other dub instance if (dstpath.existsFile()) { m_packageManager.refresh(false); return m_packageManager.getPackage(packageId, ver, dstpath); } // repeat download on corrupted zips, see #1336 foreach_reverse (i; 0..3) { import std.zip : ZipException; auto path = getTempFile(basePackageName, ".zip"); supplier.fetchPackage(path, basePackageName, dep, (options & FetchOptions.usePrerelease) != 0); // Q: continue on fail? scope(exit) std.file.remove(path.toNativeString()); logDiagnostic("Placing to %s...", placement.toNativeString()); try { m_packageManager.storeFetchedPackage(path, pinfo, dstpath); return m_packageManager.getPackage(packageId, ver, dstpath); } catch (ZipException e) { logInfo("Failed to extract zip archive for %s %s...", packageId, ver); // rethrow the exception at the end of the loop if (i == 0) throw e; } } assert(0, "Should throw a ZipException instead."); } /** Removes a specific locally cached package. This will delete the package files from disk and removes the corresponding entry from the list of known packages. Params: pack = Package instance to remove */ void remove(in Package pack) { logInfo("Removing %s in %s", pack.name, pack.path.toNativeString()); if (!m_dryRun) m_packageManager.remove(pack); } /// Compatibility overload. Use the version without a `force_remove` argument instead. void remove(in Package pack, bool force_remove) { remove(pack); } /// @see remove(string, string, RemoveLocation) enum RemoveVersionWildcard = "*"; /** Removes one or more versions of a locally cached package. This will remove a given package with a specified version from the given location. It will remove at most one package, unless `version_` is set to `RemoveVersionWildcard`. Params: package_id = Name of the package to be removed location_ = Specifies the location to look for the given package name/version. resolve_version = Callback to select package version. */ void remove(string package_id, PlacementLocation location, scope size_t delegate(in Package[] packages) resolve_version) { enforce(!package_id.empty); if (location == PlacementLocation.local) { logInfo("To remove a locally placed package, make sure you don't have any data" ~ "\nleft in it's directory and then simply remove the whole directory."); throw new Exception("dub cannot remove locally installed packages."); } Package[] packages; // Retrieve packages to be removed. foreach(pack; m_packageManager.getPackageIterator(package_id)) if (m_packageManager.isManagedPackage(pack)) packages ~= pack; // Check validity of packages to be removed. if(packages.empty) { throw new Exception("Cannot find package to remove. (" ~ "id: '" ~ package_id ~ "', location: '" ~ to!string(location) ~ "'" ~ ")"); } // Sort package list in ascending version order packages.sort!((a, b) => a.version_ < b.version_); immutable idx = resolve_version(packages); if (idx == size_t.max) return; else if (idx != packages.length) packages = packages[idx .. idx + 1]; logDebug("Removing %s packages.", packages.length); foreach(pack; packages) { try { remove(pack); logInfo("Removed %s, version %s.", package_id, pack.version_); } catch (Exception e) { logError("Failed to remove %s %s: %s", package_id, pack.version_, e.msg); logInfo("Continuing with other packages (if any)."); } } } /// Compatibility overload. Use the version without a `force_remove` argument instead. void remove(string package_id, PlacementLocation location, bool force_remove, scope size_t delegate(in Package[] packages) resolve_version) { remove(package_id, location, resolve_version); } /** Removes a specific version of a package. Params: package_id = Name of the package to be removed version_ = Identifying a version or a wild card. If an empty string is passed, the package will be removed from the location, if there is only one version retrieved. This will throw an exception, if there are multiple versions retrieved. location_ = Specifies the location to look for the given package name/version. */ void remove(string package_id, string version_, PlacementLocation location) { remove(package_id, location, (in packages) { if (version_ == RemoveVersionWildcard) return packages.length; if (version_.empty && packages.length > 1) { logError("Cannot remove package '" ~ package_id ~ "', there are multiple possibilities at location\n" ~ "'" ~ to!string(location) ~ "'."); logError("Available versions:"); foreach(pack; packages) logError(" %s", pack.version_); throw new Exception("Please specify a individual version using --version=... or use the" ~ " wildcard --version=" ~ RemoveVersionWildcard ~ " to remove all versions."); } foreach (i, p; packages) { if (p.version_ == Version(version_)) return i; } throw new Exception("Cannot find package to remove. (" ~ "id: '" ~ package_id ~ "', version: '" ~ version_ ~ "', location: '" ~ to!string(location) ~ "'" ~ ")"); }); } /// Compatibility overload. Use the version without a `force_remove` argument instead. void remove(string package_id, string version_, PlacementLocation location, bool force_remove) { remove(package_id, version_, location); } /** Adds a directory to the list of locally known packages. Forwards to `PackageManager.addLocalPackage`. Params: path = Path to the package ver = Optional version to associate with the package (can be left empty) system = Make the package known system wide instead of user wide (requires administrator privileges). See_Also: `removeLocalPackage` */ void addLocalPackage(string path, string ver, bool system) { if (m_dryRun) return; m_packageManager.addLocalPackage(makeAbsolute(path), ver, system ? LocalPackageType.system : LocalPackageType.user); } /** Removes a directory from the list of locally known packages. Forwards to `PackageManager.removeLocalPackage`. Params: path = Path to the package system = Make the package known system wide instead of user wide (requires administrator privileges). See_Also: `addLocalPackage` */ void removeLocalPackage(string path, bool system) { if (m_dryRun) return; m_packageManager.removeLocalPackage(makeAbsolute(path), system ? LocalPackageType.system : LocalPackageType.user); } /** Registers a local directory to search for packages to use for satisfying dependencies. Params: path = Path to a directory containing package directories system = Make the package known system wide instead of user wide (requires administrator privileges). See_Also: `removeSearchPath` */ void addSearchPath(string path, bool system) { if (m_dryRun) return; m_packageManager.addSearchPath(makeAbsolute(path), system ? LocalPackageType.system : LocalPackageType.user); } /** Unregisters a local directory search path. Params: path = Path to a directory containing package directories system = Make the package known system wide instead of user wide (requires administrator privileges). See_Also: `addSearchPath` */ void removeSearchPath(string path, bool system) { if (m_dryRun) return; m_packageManager.removeSearchPath(makeAbsolute(path), system ? LocalPackageType.system : LocalPackageType.user); } /** Queries all package suppliers with the given query string. Returns a list of tuples, where the first entry is the human readable name of the package supplier and the second entry is the list of matched packages. See_Also: `PackageSupplier.searchPackages` */ auto searchPackages(string query) { import std.typecons : Tuple, tuple; Tuple!(string, PackageSupplier.SearchResult[])[] results; foreach (ps; this.m_packageSuppliers) { try results ~= tuple(ps.description, ps.searchPackages(query)); catch (Exception e) { logWarn("Searching %s for '%s' failed: %s", ps.description, query, e.msg); } } return results.filter!(tup => tup[1].length); } /** Returns a list of all available versions (including branches) for a particular package. The list returned is based on the registered package suppliers. Local packages are not queried in the search for versions. See_also: `getLatestVersion` */ Version[] listPackageVersions(string name) { Version[] versions; auto basePackageName = getBasePackageName(name); foreach (ps; this.m_packageSuppliers) { try versions ~= ps.getVersions(basePackageName); catch (Exception e) { logWarn("Failed to get versions for package %s on provider %s: %s", name, ps.description, e.msg); } } return versions.sort().uniq.array; } /** Returns the latest available version for a particular package. This function returns the latest numbered version of a package. If no numbered versions are available, it will return an available branch, preferring "~master". Params: package_name: The name of the package in question. prefer_stable: If set to `true` (the default), returns the latest stable version, even if there are newer pre-release versions. See_also: `listPackageVersions` */ Version getLatestVersion(string package_name, bool prefer_stable = true) { auto vers = listPackageVersions(package_name); enforce(!vers.empty, "Failed to find any valid versions for a package name of '"~package_name~"'."); auto final_versions = vers.filter!(v => !v.isBranch && !v.isPreRelease).array; if (prefer_stable && final_versions.length) return final_versions[$-1]; else return vers[$-1]; } /** Initializes a directory with a package skeleton. Params: path = Path of the directory to create the new package in. The directory will be created if it doesn't exist. deps = List of dependencies to add to the package recipe. type = Specifies the type of the application skeleton to use. format = Determines the package recipe format to use. recipe_callback = Optional callback that can be used to customize the recipe before it gets written. */ void createEmptyPackage(NativePath path, string[] deps, string type, PackageFormat format = PackageFormat.sdl, scope void delegate(ref PackageRecipe, ref PackageFormat) recipe_callback = null, string[] app_args = []) { if (!path.absolute) path = m_rootPath ~ path; path.normalize(); string[string] depVers; string[] notFound; // keep track of any failed packages in here foreach (dep; deps) { Version ver; try { ver = getLatestVersion(dep); depVers[dep] = ver.isBranch ? ver.toString() : "~>" ~ ver.toString(); } catch (Exception e) { notFound ~= dep; } } if(notFound.length > 1){ throw new Exception(.format("Couldn't find packages: %-(%s, %).", notFound)); } else if(notFound.length == 1){ throw new Exception(.format("Couldn't find package: %-(%s, %).", notFound)); } if (m_dryRun) return; initPackage(path, depVers, type, format, recipe_callback); if (!["vibe.d", "deimos", "minimal"].canFind(type)) { runCustomInitialization(path, type, app_args); } //Act smug to the user. logInfo("Successfully created an empty project in '%s'.", path.toNativeString()); } private void runCustomInitialization(NativePath path, string type, string[] runArgs) { string packageName = type; auto template_pack = m_packageManager.getBestPackage(packageName, ">=0.0.0"); if (!template_pack) template_pack = m_packageManager.getBestPackage(packageName, "~master"); if (!template_pack) { logInfo("%s is not present, getting and storing it user wide", packageName); template_pack = fetch(packageName, Dependency(">=0.0.0"), defaultPlacementLocation, FetchOptions.none); } Package initSubPackage = m_packageManager.getSubPackage(template_pack, "init-exec", false); auto template_dub = new Dub(null, m_packageSuppliers); template_dub.loadPackage(initSubPackage); auto compiler_binary = this.defaultCompiler; GeneratorSettings settings; settings.config = "application"; settings.compiler = getCompiler(compiler_binary); settings.platform = settings.compiler.determinePlatform(settings.buildSettings, compiler_binary, m_defaultArchitecture); settings.buildType = "debug"; settings.run = true; settings.runArgs = runArgs; initSubPackage.recipe.buildSettings.workingDirectory = path.toNativeString(); template_dub.generateProject("build", settings); } /** Converts the package recipe of the loaded root package to the given format. Params: destination_file_ext = The file extension matching the desired format. Possible values are "json" or "sdl". print_only = Print the converted recipe instead of writing to disk */ void convertRecipe(string destination_file_ext, bool print_only = false) { import std.path : extension; import std.stdio : stdout; import dub.recipe.io : serializePackageRecipe, writePackageRecipe; if (print_only) { auto dst = stdout.lockingTextWriter; serializePackageRecipe(dst, m_project.rootPackage.rawRecipe, "dub."~destination_file_ext); return; } auto srcfile = m_project.rootPackage.recipePath; auto srcext = srcfile.head.name.extension; if (srcext == "."~destination_file_ext) { logInfo("Package format is already %s.", destination_file_ext); return; } writePackageRecipe(srcfile.parentPath ~ ("dub."~destination_file_ext), m_project.rootPackage.rawRecipe); removeFile(srcfile); } /** Runs DDOX to generate or serve documentation. Params: run = If set to true, serves documentation on a local web server. Otherwise generates actual HTML files. generate_args = Additional command line arguments to pass to "ddox generate-html" or "ddox serve-html". */ void runDdox(bool run, string[] generate_args = null) { import std.process : browse; if (m_dryRun) return; // allow to choose a custom ddox tool auto tool = m_project.rootPackage.recipe.ddoxTool; if (tool.empty) tool = "ddox"; auto tool_pack = m_packageManager.getBestPackage(tool, ">=0.0.0"); if (!tool_pack) tool_pack = m_packageManager.getBestPackage(tool, "~master"); if (!tool_pack) { logInfo("%s is not present, getting and storing it user wide", tool); tool_pack = fetch(tool, Dependency(">=0.0.0"), defaultPlacementLocation, FetchOptions.none); } auto ddox_dub = new Dub(null, m_packageSuppliers); ddox_dub.loadPackage(tool_pack.path); ddox_dub.upgrade(UpgradeOptions.select); auto compiler_binary = this.defaultCompiler; GeneratorSettings settings; settings.config = "application"; settings.compiler = getCompiler(compiler_binary); // TODO: not using --compiler ??? settings.platform = settings.compiler.determinePlatform(settings.buildSettings, compiler_binary, m_defaultArchitecture); settings.buildType = "debug"; settings.run = true; auto filterargs = m_project.rootPackage.recipe.ddoxFilterArgs.dup; if (filterargs.empty) filterargs = ["--min-protection=Protected", "--only-documented"]; settings.runArgs = "filter" ~ filterargs ~ "docs.json"; ddox_dub.generateProject("build", settings); auto p = tool_pack.path; p.endsWithSlash = true; auto tool_path = p.toNativeString(); if (run) { settings.runArgs = ["serve-html", "--navigation-type=ModuleTree", "docs.json", "--web-file-dir="~tool_path~"public"] ~ generate_args; browse("http://127.0.0.1:8080/"); } else { settings.runArgs = ["generate-html", "--navigation-type=ModuleTree", "docs.json", "docs"] ~ generate_args; } ddox_dub.generateProject("build", settings); if (!run) { // TODO: ddox should copy those files itself version(Windows) runCommand(`xcopy /S /D "`~tool_path~`public\*" docs\`); else runCommand("rsync -ru '"~tool_path~"public/' docs/"); } } private void updatePackageSearchPath() { if (!m_overrideSearchPath.empty) { m_packageManager.disableDefaultSearchPaths = true; m_packageManager.searchPath = [m_overrideSearchPath]; } else { auto p = environment.get("DUBPATH"); NativePath[] paths; version(Windows) enum pathsep = ";"; else enum pathsep = ":"; if (p.length) paths ~= p.split(pathsep).map!(p => NativePath(p))().array(); m_packageManager.disableDefaultSearchPaths = false; m_packageManager.searchPath = paths; } } private void determineDefaultCompiler() { import std.file : thisExePath; import std.path : buildPath, dirName, expandTilde, isAbsolute, isDirSeparator; import std.process : environment; import std.range : front; m_defaultCompiler = m_config.defaultCompiler.expandTilde; if (m_defaultCompiler.length && m_defaultCompiler.isAbsolute) return; static immutable BinaryPrefix = `$DUB_BINARY_PATH`; if(m_defaultCompiler.startsWith(BinaryPrefix)) { m_defaultCompiler = thisExePath().dirName() ~ m_defaultCompiler[BinaryPrefix.length .. $]; return; } if (!find!isDirSeparator(m_defaultCompiler).empty) throw new Exception("defaultCompiler specified in a DUB config file cannot use an unqualified relative path:\n\n" ~ m_defaultCompiler ~ "\n\nUse \"$DUB_BINARY_PATH/../path/you/want\" instead."); version (Windows) enum sep = ";", exe = ".exe"; version (Posix) enum sep = ":", exe = ""; auto compilers = ["dmd", "gdc", "gdmd", "ldc2", "ldmd2"]; // If a compiler name is specified, look for it next to dub. // Otherwise, look for any of the common compilers adjacent to dub. if (m_defaultCompiler.length) { string compilerPath = buildPath(thisExePath().dirName(), m_defaultCompiler ~ exe); if (existsFile(compilerPath)) { m_defaultCompiler = compilerPath; return; } } else { auto nextFound = compilers.find!(bin => existsFile(buildPath(thisExePath().dirName(), bin ~ exe))); if (!nextFound.empty) { m_defaultCompiler = buildPath(thisExePath().dirName(), nextFound.front ~ exe); return; } } // If nothing found next to dub, search the user's PATH, starting // with the compiler name from their DUB config file, if specified. if (m_defaultCompiler.length) compilers = m_defaultCompiler ~ compilers; auto paths = environment.get("PATH", "").splitter(sep).map!NativePath; auto res = compilers.find!(bin => paths.canFind!(p => existsFile(p ~ (bin~exe)))); m_defaultCompiler = res.empty ? compilers[0] : res.front; } private NativePath makeAbsolute(NativePath p) const { return p.absolute ? p : m_rootPath ~ p; } private NativePath makeAbsolute(string p) const { return makeAbsolute(NativePath(p)); } } /// Option flags for `Dub.fetch` enum FetchOptions { none = 0, forceBranchUpgrade = 1<<0, usePrerelease = 1<<1, forceRemove = 1<<2, /// Deprecated, does nothing. printOnly = 1<<3, } /// Option flags for `Dub.upgrade` enum UpgradeOptions { none = 0, upgrade = 1<<1, /// Upgrade existing packages preRelease = 1<<2, /// inclde pre-release versions in upgrade forceRemove = 1<<3, /// Deprecated, does nothing. select = 1<<4, /// Update the dub.selections.json file with the upgraded versions dryRun = 1<<5, /// Instead of downloading new packages, just print a message to notify the user of their existence /*deprecated*/ printUpgradesOnly = dryRun, /// deprecated, use dryRun instead /*deprecated*/ useCachedResult = 1<<6, /// deprecated, has no effect noSaveSelections = 1<<7, /// Don't store updated selections on disk } /// Determines which of the default package suppliers are queried for packages. enum SkipPackageSuppliers { none, /// Uses all configured package suppliers. standard, /// Does not use the default package suppliers (`defaultPackageSuppliers`). configured, /// Does not use default suppliers or suppliers configured in DUB's configuration file all /// Uses only manually specified package suppliers. } private class DependencyVersionResolver : DependencyResolver!(Dependency, Dependency) { protected { Dub m_dub; UpgradeOptions m_options; Dependency[][string] m_packageVersions; Package[string] m_remotePackages; SelectedVersions m_selectedVersions; Package m_rootPackage; bool[string] m_packagesToUpgrade; Package[PackageDependency] m_packages; TreeNodes[][TreeNode] m_children; } this(Dub dub, UpgradeOptions options) { m_dub = dub; m_options = options; } void addPackageToUpgrade(string name) { m_packagesToUpgrade[name] = true; } Dependency[string] resolve(Package root, SelectedVersions selected_versions) { m_rootPackage = root; m_selectedVersions = selected_versions; return super.resolve(TreeNode(root.name, Dependency(root.version_)), (m_options & UpgradeOptions.printUpgradesOnly) == 0); } protected bool isFixedPackage(string pack) { return m_packagesToUpgrade !is null && pack !in m_packagesToUpgrade; } protected override Dependency[] getAllConfigs(string pack) { if (auto pvers = pack in m_packageVersions) return *pvers; if ((!(m_options & UpgradeOptions.upgrade) || isFixedPackage(pack)) && m_selectedVersions.hasSelectedVersion(pack)) { auto ret = [m_selectedVersions.getSelectedVersion(pack)]; logDiagnostic("Using fixed selection %s %s", pack, ret[0]); m_packageVersions[pack] = ret; return ret; } logDiagnostic("Search for versions of %s (%s package suppliers)", pack, m_dub.m_packageSuppliers.length); Version[] versions; foreach (p; m_dub.packageManager.getPackageIterator(pack)) versions ~= p.version_; foreach (ps; m_dub.m_packageSuppliers) { try { auto vers = ps.getVersions(pack); vers.reverse(); if (!vers.length) { logDiagnostic("No versions for %s for %s", pack, ps.description); continue; } versions ~= vers; break; } catch (Exception e) { logWarn("Package %s not found in %s: %s", pack, ps.description, e.msg); logDebug("Full error: %s", e.toString().sanitize); } } // sort by version, descending, and remove duplicates versions = versions.sort!"a>b".uniq.array; // move pre-release versions to the back of the list if no preRelease flag is given if (!(m_options & UpgradeOptions.preRelease)) versions = versions.filter!(v => !v.isPreRelease).array ~ versions.filter!(v => v.isPreRelease).array; // filter out invalid/unreachable dependency specs versions = versions.filter!((v) { bool valid = getPackage(pack, Dependency(v)) !is null; if (!valid) logDiagnostic("Excluding invalid dependency specification %s %s from dependency resolution process.", pack, v); return valid; }).array; if (!versions.length) logDiagnostic("Nothing found for %s", pack); else logDiagnostic("Return for %s: %s", pack, versions); auto ret = versions.map!(v => Dependency(v)).array; m_packageVersions[pack] = ret; return ret; } protected override Dependency[] getSpecificConfigs(string pack, TreeNodes nodes) { if (!nodes.configs.path.empty && getPackage(pack, nodes.configs)) return [nodes.configs]; else return null; } protected override TreeNodes[] getChildren(TreeNode node) { if (auto pc = node in m_children) return *pc; auto ret = getChildrenRaw(node); m_children[node] = ret; return ret; } private final TreeNodes[] getChildrenRaw(TreeNode node) { import std.array : appender; auto ret = appender!(TreeNodes[]); auto pack = getPackage(node.pack, node.config); if (!pack) { // this can hapen when the package description contains syntax errors logDebug("Invalid package in dependency tree: %s %s", node.pack, node.config); return null; } auto basepack = pack.basePackage; foreach (d; pack.getAllDependenciesRange()) { auto dbasename = getBasePackageName(d.name); // detect dependencies to the root package (or sub packages thereof) if (dbasename == basepack.name) { auto absdeppath = d.spec.mapToPath(pack.path).path; absdeppath.endsWithSlash = true; auto subpack = m_dub.m_packageManager.getSubPackage(basepack, getSubPackageName(d.name), true); if (subpack) { auto desireddeppath = d.name == dbasename ? basepack.path : subpack.path; desireddeppath.endsWithSlash = true; enforce(d.spec.path.empty || absdeppath == desireddeppath, format("Dependency from %s to root package references wrong path: %s vs. %s", node.pack, absdeppath.toNativeString(), desireddeppath.toNativeString())); } ret ~= TreeNodes(d.name, node.config); continue; } DependencyType dt; if (d.spec.optional) { if (d.spec.default_) dt = DependencyType.optionalDefault; else dt = DependencyType.optional; } else dt = DependencyType.required; Dependency dspec = d.spec.mapToPath(pack.path); // if not upgrading, use the selected version if (!(m_options & UpgradeOptions.upgrade) && m_selectedVersions && m_selectedVersions.hasSelectedVersion(dbasename)) dspec = m_selectedVersions.getSelectedVersion(dbasename); // keep selected optional dependencies and avoid non-selected optional-default dependencies by default if (m_selectedVersions && !m_selectedVersions.bare) { if (dt == DependencyType.optionalDefault && !m_selectedVersions.hasSelectedVersion(dbasename)) dt = DependencyType.optional; else if (dt == DependencyType.optional && m_selectedVersions.hasSelectedVersion(dbasename)) dt = DependencyType.optionalDefault; } ret ~= TreeNodes(d.name, dspec, dt); } return ret.data; } protected override bool matches(Dependency configs, Dependency config) { if (!configs.path.empty) return configs.path == config.path; return configs.merge(config).valid; } private Package getPackage(string name, Dependency dep) { auto key = PackageDependency(name, dep); if (auto pp = key in m_packages) return *pp; auto p = getPackageRaw(name, dep); m_packages[key] = p; return p; } private Package getPackageRaw(string name, Dependency dep) { auto basename = getBasePackageName(name); // for sub packages, first try to get them from the base package if (basename != name) { auto subname = getSubPackageName(name); auto basepack = getPackage(basename, dep); if (!basepack) return null; if (auto sp = m_dub.m_packageManager.getSubPackage(basepack, subname, true)) { return sp; } else if (!basepack.subPackages.canFind!(p => p.path.length)) { // note: external sub packages are handled further below auto spr = basepack.getInternalSubPackage(subname); if (!spr.isNull) { auto sp = new Package(spr.get, basepack.path, basepack); m_remotePackages[sp.name] = sp; return sp; } else { logDiagnostic("Sub package %s doesn't exist in %s %s.", name, basename, dep.version_); return null; } } else if (auto ret = m_dub.m_packageManager.getBestPackage(name, dep)) { return ret; } else { logDiagnostic("External sub package %s %s not found.", name, dep.version_); return null; } } // shortcut if the referenced package is the root package if (basename == m_rootPackage.basePackage.name) return m_rootPackage.basePackage; if (!dep.path.empty) { try { auto ret = m_dub.packageManager.getOrLoadPackage(dep.path); if (dep.matches(ret.version_)) return ret; } catch (Exception e) { logDiagnostic("Failed to load path based dependency %s: %s", name, e.msg); logDebug("Full error: %s", e.toString().sanitize); return null; } } if (auto ret = m_dub.m_packageManager.getBestPackage(name, dep)) return ret; auto key = name ~ ":" ~ dep.version_.toString(); if (auto ret = key in m_remotePackages) return *ret; auto prerelease = (m_options & UpgradeOptions.preRelease) != 0; auto rootpack = name.split(":")[0]; foreach (ps; m_dub.m_packageSuppliers) { if (rootpack == name) { try { auto desc = ps.fetchPackageRecipe(name, dep, prerelease); if (desc.type == Json.Type.null_) continue; auto ret = new Package(desc); m_remotePackages[key] = ret; return ret; } catch (Exception e) { logDiagnostic("Metadata for %s %s could not be downloaded from %s: %s", name, dep, ps.description, e.msg); logDebug("Full error: %s", e.toString().sanitize); } } else { logDiagnostic("Package %s not found in base package description (%s). Downloading whole package.", name, dep.version_.toString()); try { FetchOptions fetchOpts; fetchOpts |= prerelease ? FetchOptions.usePrerelease : FetchOptions.none; m_dub.fetch(rootpack, dep, m_dub.defaultPlacementLocation, fetchOpts, "need sub package description"); auto ret = m_dub.m_packageManager.getBestPackage(name, dep); if (!ret) { logWarn("Package %s %s doesn't have a sub package %s", rootpack, dep.version_, name); return null; } m_remotePackages[key] = ret; return ret; } catch (Exception e) { logDiagnostic("Package %s could not be downloaded from %s: %s", rootpack, ps.description, e.msg); logDebug("Full error: %s", e.toString().sanitize); } } } m_remotePackages[key] = null; logWarn("Package %s %s could not be loaded either locally, or from the configured package registries.", name, dep); return null; } } private struct SpecialDirs { NativePath temp; NativePath userSettings; NativePath systemSettings; NativePath localRepository; } private class DubConfig { private { DubConfig m_parentConfig; Json m_data; } this(Json data, DubConfig parent_config) { m_data = data; m_parentConfig = parent_config; } @property string[] registryURLs() { string[] ret; if (auto pv = "registryUrls" in m_data) ret = (*pv).deserializeJson!(string[]); if (m_parentConfig) ret ~= m_parentConfig.registryURLs; return ret; } @property SkipPackageSuppliers skipRegistry() { if(auto pv = "skipRegistry" in m_data) return to!SkipPackageSuppliers((*pv).get!string); if (m_parentConfig) return m_parentConfig.skipRegistry; return SkipPackageSuppliers.none; } @property NativePath[] customCachePaths() { import std.algorithm.iteration : map; import std.array : array; NativePath[] ret; if (auto pv = "customCachePaths" in m_data) ret = (*pv).deserializeJson!(string[]) .map!(s => NativePath(s)) .array; if (m_parentConfig) ret ~= m_parentConfig.customCachePaths; return ret; } @property string defaultCompiler() const { if (auto pv = "defaultCompiler" in m_data) return pv.get!string; if (m_parentConfig) return m_parentConfig.defaultCompiler; return null; } @property string defaultArchitecture() const { if(auto pv = "defaultArchitecture" in m_data) return (*pv).get!string; if (m_parentConfig) return m_parentConfig.defaultArchitecture; return null; } } dub-1.19.0/source/dub/generators/000077500000000000000000000000001360435400500165775ustar00rootroot00000000000000dub-1.19.0/source/dub/generators/build.d000066400000000000000000000632121360435400500200470ustar00rootroot00000000000000/** Generator for direct compiler builds. Copyright: © 2013-2013 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.generators.build; import dub.compilers.compiler; import dub.compilers.utils; import dub.generators.generator; import dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import dub.package_; import dub.packagemanager; import dub.project; import std.algorithm; import std.array; import std.conv; import std.exception; import std.file; import std.process; import std.string; import std.encoding : sanitize; string getObjSuffix(in ref BuildPlatform platform) { return platform.platform.canFind("windows") ? ".obj" : ".o"; } class BuildGenerator : ProjectGenerator { private { PackageManager m_packageMan; NativePath[] m_temporaryFiles; } this(Project project) { super(project); m_packageMan = project.packageManager; } override void generateTargets(GeneratorSettings settings, in TargetInfo[string] targets) { scope (exit) cleanupTemporaries(); void checkPkgRequirements(const(Package) pkg) { const tr = pkg.recipe.toolchainRequirements; tr.checkPlatform(settings.platform, pkg.name); } checkPkgRequirements(m_project.rootPackage); foreach (pkg; m_project.dependencies) checkPkgRequirements(pkg); auto root_ti = targets[m_project.rootPackage.name]; enforce(!(settings.rdmd && root_ti.buildSettings.targetType == TargetType.none), "Building package with target type \"none\" with rdmd is not supported yet."); logInfo("Performing \"%s\" build using %s for %-(%s, %).", settings.buildType, settings.platform.compilerBinary, settings.platform.architecture); bool any_cached = false; NativePath[string] target_paths; bool[string] visited; void buildTargetRec(string target) { if (target in visited) return; visited[target] = true; auto ti = targets[target]; foreach (dep; ti.dependencies) buildTargetRec(dep); NativePath[] additional_dep_files; auto bs = ti.buildSettings.dup; foreach (ldep; ti.linkDependencies) { if (bs.targetType != TargetType.staticLibrary && !(bs.options & BuildOption.syntaxOnly)) { bs.addSourceFiles(target_paths[ldep].toNativeString()); } else { additional_dep_files ~= target_paths[ldep]; } } NativePath tpath; if (bs.targetType != TargetType.none) if (buildTarget(settings, bs, ti.pack, ti.config, ti.packages, additional_dep_files, tpath)) any_cached = true; target_paths[target] = tpath; } // build all targets if (settings.rdmd || root_ti.buildSettings.targetType == TargetType.staticLibrary) { // RDMD always builds everything at once and static libraries don't need their // dependencies to be built NativePath tpath; buildTarget(settings, root_ti.buildSettings.dup, m_project.rootPackage, root_ti.config, root_ti.packages, null, tpath); } else { buildTargetRec(m_project.rootPackage.name); if (any_cached) { logInfo("To force a rebuild of up-to-date targets, run again with --force."); } } } override void performPostGenerateActions(GeneratorSettings settings, in TargetInfo[string] targets) { // run the generated executable auto buildsettings = targets[m_project.rootPackage.name].buildSettings.dup; if (settings.run && !(buildsettings.options & BuildOption.syntaxOnly)) { NativePath exe_file_path; if (m_tempTargetExecutablePath.empty) exe_file_path = getTargetPath(buildsettings, settings); else exe_file_path = m_tempTargetExecutablePath ~ settings.compiler.getTargetFileName(buildsettings, settings.platform); runTarget(exe_file_path, buildsettings, settings.runArgs, settings); } } private bool buildTarget(GeneratorSettings settings, BuildSettings buildsettings, in Package pack, string config, in Package[] packages, in NativePath[] additional_dep_files, out NativePath target_path) { auto cwd = NativePath(getcwd()); bool generate_binary = !(buildsettings.options & BuildOption.syntaxOnly); auto build_id = computeBuildID(config, buildsettings, settings); // make all paths relative to shrink the command line string makeRelative(string path) { return shrinkPath(NativePath(path), cwd); } foreach (ref f; buildsettings.sourceFiles) f = makeRelative(f); foreach (ref p; buildsettings.importPaths) p = makeRelative(p); foreach (ref p; buildsettings.stringImportPaths) p = makeRelative(p); // perform the actual build bool cached = false; if (settings.rdmd) performRDMDBuild(settings, buildsettings, pack, config, target_path); else if (settings.direct || !generate_binary) performDirectBuild(settings, buildsettings, pack, config, target_path); else cached = performCachedBuild(settings, buildsettings, pack, config, build_id, packages, additional_dep_files, target_path); // HACK: cleanup dummy doc files, we shouldn't specialize on buildType // here and the compiler shouldn't need dummy doc output. if (settings.buildType == "ddox") { if ("__dummy.html".exists) removeFile("__dummy.html"); if ("__dummy_docs".exists) rmdirRecurse("__dummy_docs"); } // run post-build commands if (!cached && buildsettings.postBuildCommands.length) { logInfo("Running post-build commands..."); runBuildCommands(buildsettings.postBuildCommands, pack, m_project, settings, buildsettings); } return cached; } private bool performCachedBuild(GeneratorSettings settings, BuildSettings buildsettings, in Package pack, string config, string build_id, in Package[] packages, in NativePath[] additional_dep_files, out NativePath target_binary_path) { auto cwd = NativePath(getcwd()); NativePath target_path; if (settings.tempBuild) { string packageName = pack.basePackage is null ? pack.name : pack.basePackage.name; m_tempTargetExecutablePath = target_path = getTempDir() ~ format(".dub/build/%s-%s/%s/", packageName, pack.version_, build_id); } else target_path = pack.path ~ format(".dub/build/%s/", build_id); if (!settings.force && isUpToDate(target_path, buildsettings, settings, pack, packages, additional_dep_files)) { logInfo("%s %s: target for configuration \"%s\" is up to date.", pack.name, pack.version_, config); logDiagnostic("Using existing build in %s.", target_path.toNativeString()); target_binary_path = target_path ~ settings.compiler.getTargetFileName(buildsettings, settings.platform); if (!settings.tempBuild) copyTargetFile(target_path, buildsettings, settings); return true; } if (!isWritableDir(target_path, true)) { if (!settings.tempBuild) logInfo("Build directory %s is not writable. Falling back to direct build in the system's temp folder.", target_path.relativeTo(cwd).toNativeString()); performDirectBuild(settings, buildsettings, pack, config, target_path); return false; } logInfo("%s %s: building configuration \"%s\"...", pack.name, pack.version_, config); if( buildsettings.preBuildCommands.length ){ logInfo("Running pre-build commands..."); runBuildCommands(buildsettings.preBuildCommands, pack, m_project, settings, buildsettings); } // override target path auto cbuildsettings = buildsettings; cbuildsettings.targetPath = shrinkPath(target_path, cwd); buildWithCompiler(settings, cbuildsettings); target_binary_path = getTargetPath(cbuildsettings, settings); if (!settings.tempBuild) copyTargetFile(target_path, buildsettings, settings); return false; } private void performRDMDBuild(GeneratorSettings settings, ref BuildSettings buildsettings, in Package pack, string config, out NativePath target_path) { auto cwd = NativePath(getcwd()); //Added check for existence of [AppNameInPackagejson].d //If exists, use that as the starting file. NativePath mainsrc; if (buildsettings.mainSourceFile.length) { mainsrc = NativePath(buildsettings.mainSourceFile); if (!mainsrc.absolute) mainsrc = pack.path ~ mainsrc; } else { mainsrc = getMainSourceFile(pack); logWarn(`Package has no "mainSourceFile" defined. Using best guess: %s`, mainsrc.relativeTo(pack.path).toNativeString()); } // do not pass all source files to RDMD, only the main source file buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(s => !s.endsWith(".d"))().array(); settings.compiler.prepareBuildSettings(buildsettings, settings.platform, BuildSetting.commandLine); auto generate_binary = !buildsettings.dflags.canFind("-o-"); // Create start script, which will be used by the calling bash/cmd script. // build "rdmd --force %DFLAGS% -I%~dp0..\source -Jviews -Isource @deps.txt %LIBS% source\app.d" ~ application arguments // or with "/" instead of "\" bool tmp_target = false; if (generate_binary) { if (settings.tempBuild || (settings.run && !isWritableDir(NativePath(buildsettings.targetPath), true))) { import std.random; auto rnd = to!string(uniform(uint.min, uint.max)) ~ "-"; auto tmpdir = getTempDir()~".rdmd/source/"; buildsettings.targetPath = tmpdir.toNativeString(); buildsettings.targetName = rnd ~ buildsettings.targetName; m_temporaryFiles ~= tmpdir; tmp_target = true; } target_path = getTargetPath(buildsettings, settings); settings.compiler.setTarget(buildsettings, settings.platform); } logDiagnostic("Application output name is '%s'", settings.compiler.getTargetFileName(buildsettings, settings.platform)); string[] flags = ["--build-only", "--compiler="~settings.platform.compilerBinary]; if (settings.force) flags ~= "--force"; flags ~= buildsettings.dflags; flags ~= mainsrc.relativeTo(cwd).toNativeString(); if (buildsettings.preBuildCommands.length){ logInfo("Running pre-build commands..."); runCommands(buildsettings.preBuildCommands); } logInfo("%s %s: building configuration \"%s\"...", pack.name, pack.version_, config); logInfo("Running rdmd..."); logDiagnostic("rdmd %s", join(flags, " ")); auto rdmd_pid = spawnProcess("rdmd" ~ flags); auto result = rdmd_pid.wait(); enforce(result == 0, "Build command failed with exit code "~to!string(result)); if (tmp_target) { m_temporaryFiles ~= target_path; foreach (f; buildsettings.copyFiles) m_temporaryFiles ~= NativePath(buildsettings.targetPath).parentPath ~ NativePath(f).head; } } private void performDirectBuild(GeneratorSettings settings, ref BuildSettings buildsettings, in Package pack, string config, out NativePath target_path) { auto cwd = NativePath(getcwd()); auto generate_binary = !(buildsettings.options & BuildOption.syntaxOnly); // make file paths relative to shrink the command line foreach (ref f; buildsettings.sourceFiles) { auto fp = NativePath(f); if( fp.absolute ) fp = fp.relativeTo(cwd); f = fp.toNativeString(); } logInfo("%s %s: building configuration \"%s\"...", pack.name, pack.version_, config); // make all target/import paths relative string makeRelative(string path) { auto p = NativePath(path); // storing in a separate temprary to work around #601 auto prel = p.absolute ? p.relativeTo(cwd) : p; return prel.toNativeString(); } buildsettings.targetPath = makeRelative(buildsettings.targetPath); foreach (ref p; buildsettings.importPaths) p = makeRelative(p); foreach (ref p; buildsettings.stringImportPaths) p = makeRelative(p); bool is_temp_target = false; if (generate_binary) { if (settings.tempBuild || (settings.run && !isWritableDir(NativePath(buildsettings.targetPath), true))) { import std.random; auto rnd = to!string(uniform(uint.min, uint.max)); auto tmppath = getTempDir()~("dub/"~rnd~"/"); buildsettings.targetPath = tmppath.toNativeString(); m_temporaryFiles ~= tmppath; is_temp_target = true; } target_path = getTargetPath(buildsettings, settings); } if( buildsettings.preBuildCommands.length ){ logInfo("Running pre-build commands..."); runBuildCommands(buildsettings.preBuildCommands, pack, m_project, settings, buildsettings); } buildWithCompiler(settings, buildsettings); if (is_temp_target) { m_temporaryFiles ~= target_path; foreach (f; buildsettings.copyFiles) m_temporaryFiles ~= NativePath(buildsettings.targetPath).parentPath ~ NativePath(f).head; } } private string computeBuildID(string config, in BuildSettings buildsettings, GeneratorSettings settings) { import std.digest; import std.digest.md; import std.bitmanip; MD5 hash; hash.start(); void addHash(in string[] strings...) { foreach (s; strings) { hash.put(cast(ubyte[])s); hash.put(0); } hash.put(0); } void addHashI(int value) { hash.put(nativeToLittleEndian(value)); } addHash(buildsettings.versions); addHash(buildsettings.debugVersions); //addHash(buildsettings.versionLevel); //addHash(buildsettings.debugLevel); addHash(buildsettings.dflags); addHash(buildsettings.lflags); addHash((cast(uint)buildsettings.options).to!string); addHash(buildsettings.stringImportPaths); addHash(buildsettings.importPaths); addHash(settings.platform.architecture); addHash(settings.platform.compilerBinary); addHash(settings.platform.compiler); addHashI(settings.platform.frontendVersion); auto hashstr = hash.finish().toHexString().idup; return format("%s-%s-%s-%s-%s_%s-%s", config, settings.buildType, settings.platform.platform.join("."), settings.platform.architecture.join("."), settings.platform.compiler, settings.platform.frontendVersion, hashstr); } private void copyTargetFile(NativePath build_path, BuildSettings buildsettings, GeneratorSettings settings) { auto filename = settings.compiler.getTargetFileName(buildsettings, settings.platform); auto src = build_path ~ filename; logDiagnostic("Copying target from %s to %s", src.toNativeString(), buildsettings.targetPath); if (!existsFile(NativePath(buildsettings.targetPath))) mkdirRecurse(buildsettings.targetPath); hardLinkFile(src, NativePath(buildsettings.targetPath) ~ filename, true); } private bool isUpToDate(NativePath target_path, BuildSettings buildsettings, GeneratorSettings settings, in Package main_pack, in Package[] packages, in NativePath[] additional_dep_files) { import std.datetime; auto targetfile = target_path ~ settings.compiler.getTargetFileName(buildsettings, settings.platform); if (!existsFile(targetfile)) { logDiagnostic("Target '%s' doesn't exist, need rebuild.", targetfile.toNativeString()); return false; } auto targettime = getFileInfo(targetfile).timeModified; auto allfiles = appender!(string[]); allfiles ~= buildsettings.sourceFiles; allfiles ~= buildsettings.importFiles; allfiles ~= buildsettings.stringImportFiles; allfiles ~= buildsettings.extraDependencyFiles; // TODO: add library files foreach (p; packages) allfiles ~= (p.recipePath != NativePath.init ? p : p.basePackage).recipePath.toNativeString(); foreach (f; additional_dep_files) allfiles ~= f.toNativeString(); bool checkSelectedVersions = !settings.single; if (checkSelectedVersions && main_pack is m_project.rootPackage && m_project.rootPackage.getAllDependencies().length > 0) allfiles ~= (main_pack.path ~ SelectedVersions.defaultFile).toNativeString(); foreach (file; allfiles.data) { if (!existsFile(file)) { logDiagnostic("File %s doesn't exist, triggering rebuild.", file); return false; } auto ftime = getFileInfo(file).timeModified; if (ftime > Clock.currTime) logWarn("File '%s' was modified in the future. Please re-save.", file); if (ftime > targettime) { logDiagnostic("File '%s' modified, need rebuild.", file); return false; } } return true; } /// Output an unique name to represent the source file. /// Calls with path that resolve to the same file on the filesystem will return the same, /// unless they include different symbolic links (which are not resolved). static string pathToObjName(in ref BuildPlatform platform, string path) { import std.digest.crc : crc32Of; import std.path : buildNormalizedPath, dirSeparator, relativePath, stripDrive; if (path.endsWith(".d")) path = path[0 .. $-2]; auto ret = buildNormalizedPath(getcwd(), path).replace(dirSeparator, "."); auto idx = ret.lastIndexOf('.'); const objSuffix = getObjSuffix(platform); return idx < 0 ? ret ~ objSuffix : format("%s_%(%02x%)%s", ret[idx+1 .. $], crc32Of(ret[0 .. idx]), objSuffix); } /// Compile a single source file (srcFile), and write the object to objName. static string compileUnit(string srcFile, string objName, BuildSettings bs, GeneratorSettings gs) { NativePath tempobj = NativePath(bs.targetPath)~objName; string objPath = tempobj.toNativeString(); bs.libs = null; bs.lflags = null; bs.sourceFiles = [ srcFile ]; bs.targetType = TargetType.object; gs.compiler.prepareBuildSettings(bs, gs.platform, BuildSetting.commandLine); gs.compiler.setTarget(bs, gs.platform, objPath); gs.compiler.invoke(bs, gs.platform, gs.compileCallback); return objPath; } private void buildWithCompiler(GeneratorSettings settings, BuildSettings buildsettings) { auto generate_binary = !(buildsettings.options & BuildOption.syntaxOnly); auto is_static_library = buildsettings.targetType == TargetType.staticLibrary || buildsettings.targetType == TargetType.library; scope (failure) { logDiagnostic("FAIL %s %s %s" , buildsettings.targetPath, buildsettings.targetName, buildsettings.targetType); auto tpath = getTargetPath(buildsettings, settings); if (generate_binary && existsFile(tpath)) removeFile(tpath); } if (settings.buildMode == BuildMode.singleFile && generate_binary) { import std.parallelism, std.range : walkLength; auto lbuildsettings = buildsettings; auto srcs = buildsettings.sourceFiles.filter!(f => !isLinkerFile(settings.platform, f)); auto objs = new string[](srcs.walkLength); void compileSource(size_t i, string src) { logInfo("Compiling %s...", src); const objPath = pathToObjName(settings.platform, src); objs[i] = compileUnit(src, objPath, buildsettings, settings); } if (settings.parallelBuild) { foreach (i, src; srcs.parallel(1)) compileSource(i, src); } else { foreach (i, src; srcs.array) compileSource(i, src); } logInfo("Linking..."); lbuildsettings.sourceFiles = is_static_library ? [] : lbuildsettings.sourceFiles.filter!(f => isLinkerFile(settings.platform, f)).array; settings.compiler.setTarget(lbuildsettings, settings.platform); settings.compiler.prepareBuildSettings(lbuildsettings, settings.platform, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles); settings.compiler.invokeLinker(lbuildsettings, settings.platform, objs, settings.linkCallback); // NOTE: separate compile/link is not yet enabled for GDC. } else if (generate_binary && (settings.buildMode == BuildMode.allAtOnce || settings.compiler.name == "gdc" || is_static_library)) { // don't include symbols of dependencies (will be included by the top level target) if (is_static_library) buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(f => !isLinkerFile(settings.platform, f)).array; // setup for command line settings.compiler.setTarget(buildsettings, settings.platform); settings.compiler.prepareBuildSettings(buildsettings, settings.platform, BuildSetting.commandLine); // invoke the compiler settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback); } else { // determine path for the temporary object file string tempobjname = buildsettings.targetName ~ getObjSuffix(settings.platform); NativePath tempobj = NativePath(buildsettings.targetPath) ~ tempobjname; // setup linker command line auto lbuildsettings = buildsettings; lbuildsettings.sourceFiles = lbuildsettings.sourceFiles.filter!(f => isLinkerFile(settings.platform, f)).array; if (generate_binary) settings.compiler.setTarget(lbuildsettings, settings.platform); settings.compiler.prepareBuildSettings(lbuildsettings, settings.platform, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles); // setup compiler command line buildsettings.libs = null; buildsettings.lflags = null; if (generate_binary) buildsettings.addDFlags("-c", "-of"~tempobj.toNativeString()); buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(f => !isLinkerFile(settings.platform, f)).array; settings.compiler.prepareBuildSettings(buildsettings, settings.platform, BuildSetting.commandLine); settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback); if (generate_binary) { logInfo("Linking..."); settings.compiler.invokeLinker(lbuildsettings, settings.platform, [tempobj.toNativeString()], settings.linkCallback); } } } private void runTarget(NativePath exe_file_path, in BuildSettings buildsettings, string[] run_args, GeneratorSettings settings) { if (buildsettings.targetType == TargetType.executable) { auto cwd = NativePath(getcwd()); auto runcwd = cwd; if (buildsettings.workingDirectory.length) { runcwd = NativePath(buildsettings.workingDirectory); if (!runcwd.absolute) runcwd = cwd ~ runcwd; logDiagnostic("Switching to %s", runcwd.toNativeString()); chdir(runcwd.toNativeString()); } scope(exit) chdir(cwd.toNativeString()); if (!exe_file_path.absolute) exe_file_path = cwd ~ exe_file_path; auto exe_path_string = exe_file_path.relativeTo(runcwd).toNativeString(); version (Posix) { if (!exe_path_string.startsWith(".") && !exe_path_string.startsWith("/")) exe_path_string = "./" ~ exe_path_string; } version (Windows) { if (!exe_path_string.startsWith(".") && (exe_path_string.length < 2 || exe_path_string[1] != ':')) exe_path_string = ".\\" ~ exe_path_string; } runPreRunCommands(m_project.rootPackage, m_project, settings, buildsettings); logInfo("Running %s %s", exe_path_string, run_args.join(" ")); if (settings.runCallback) { auto res = execute(exe_path_string ~ run_args); settings.runCallback(res.status, res.output); settings.targetExitStatus = res.status; runPostRunCommands(m_project.rootPackage, m_project, settings, buildsettings); } else { auto prg_pid = spawnProcess(exe_path_string ~ run_args); auto result = prg_pid.wait(); settings.targetExitStatus = result; runPostRunCommands(m_project.rootPackage, m_project, settings, buildsettings); enforce(result == 0, "Program exited with code "~to!string(result)); } } else enforce(false, "Target is a library. Skipping execution."); } private void runPreRunCommands(in Package pack, in Project proj, in GeneratorSettings settings, in BuildSettings buildsettings) { if (buildsettings.preRunCommands.length) { logInfo("Running pre-run commands..."); runBuildCommands(buildsettings.preRunCommands, pack, proj, settings, buildsettings); } } private void runPostRunCommands(in Package pack, in Project proj, in GeneratorSettings settings, in BuildSettings buildsettings) { if (buildsettings.postRunCommands.length) { logInfo("Running post-run commands..."); runBuildCommands(buildsettings.postRunCommands, pack, proj, settings, buildsettings); } } private void cleanupTemporaries() { foreach_reverse (f; m_temporaryFiles) { try { if (f.endsWithSlash) rmdir(f.toNativeString()); else remove(f.toNativeString()); } catch (Exception e) { logWarn("Failed to remove temporary file '%s': %s", f.toNativeString(), e.msg); logDiagnostic("Full error: %s", e.toString().sanitize); } } m_temporaryFiles = null; } } private NativePath getMainSourceFile(in Package prj) { foreach (f; ["source/app.d", "src/app.d", "source/"~prj.name~".d", "src/"~prj.name~".d"]) if (existsFile(prj.path ~ f)) return prj.path ~ f; return prj.path ~ "source/app.d"; } private NativePath getTargetPath(in ref BuildSettings bs, in ref GeneratorSettings settings) { return NativePath(bs.targetPath) ~ settings.compiler.getTargetFileName(bs, settings.platform); } private string shrinkPath(NativePath path, NativePath base) { auto orig = path.toNativeString(); if (!path.absolute) return orig; auto ret = path.relativeTo(base).toNativeString(); return ret.length < orig.length ? ret : orig; } unittest { assert(shrinkPath(NativePath("/foo/bar/baz"), NativePath("/foo")) == NativePath("bar/baz").toNativeString()); assert(shrinkPath(NativePath("/foo/bar/baz"), NativePath("/foo/baz")) == NativePath("../bar/baz").toNativeString()); assert(shrinkPath(NativePath("/foo/bar/baz"), NativePath("/bar/")) == NativePath("/foo/bar/baz").toNativeString()); assert(shrinkPath(NativePath("/foo/bar/baz"), NativePath("/bar/baz")) == NativePath("/foo/bar/baz").toNativeString()); } unittest { // issue #1235 - pass no library files to compiler command line when building a static lib import dub.internal.vibecompat.data.json : parseJsonString; import dub.compilers.gdc : GDCCompiler; import dub.platform : determinePlatform; version (Windows) auto libfile = "bar.lib"; else auto libfile = "bar.a"; auto desc = parseJsonString(`{"name": "test", "targetType": "library", "sourceFiles": ["foo.d", "`~libfile~`"]}`); auto pack = new Package(desc, NativePath("/tmp/fooproject")); auto pman = new PackageManager(pack.path, NativePath("/tmp/foo/"), NativePath("/tmp/foo/"), false); auto prj = new Project(pman, pack); final static class TestCompiler : GDCCompiler { override void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback) { assert(!settings.dflags[].any!(f => f.canFind("bar"))); } override void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback) { assert(false); } } GeneratorSettings settings; settings.platform = BuildPlatform(determinePlatform(), ["x86"], "gdc", "test", 2075); settings.compiler = new TestCompiler; settings.config = "library"; settings.buildType = "debug"; settings.tempBuild = true; auto gen = new BuildGenerator(prj); gen.generate(settings); } dub-1.19.0/source/dub/generators/cmake.d000066400000000000000000000113411360435400500200240ustar00rootroot00000000000000/** Generator for CMake build scripts Copyright: © 2015 Steven Dwy License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Steven Dwy */ module dub.generators.cmake; import dub.compilers.buildsettings; import dub.generators.generator; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.inet.path; import dub.project; import std.algorithm: map, uniq; import std.algorithm : stdsort = sort; // to avoid clashing with built-in sort import std.array: appender, join, replace; import std.stdio: File, write; import std.string: format; class CMakeGenerator: ProjectGenerator { this(Project project) { super(project); } override void generateTargets(GeneratorSettings settings, in TargetInfo[string] targets) { auto script = appender!(char[]); auto scripts = appender!(string[]); bool[string] visited; NativePath projectRoot = m_project.rootPackage.path; NativePath cmakeListsPath = projectRoot ~ "CMakeLists.txt"; foreach(name, info; targets) { if(visited.get(name, false)) continue; visited[name] = true; name = name.sanitize; string targetType; string libType; bool addTarget = true; switch(info.buildSettings.targetType) with(TargetType) { case autodetect: throw new Exception("Don't know what to do about autodetect target type"); case executable: targetType = "executable"; break; case dynamicLibrary: libType = "SHARED"; goto case; case library: case staticLibrary: targetType = "library"; break; case sourceLibrary: addTarget = false; break; case none: continue; default: assert(false); } script.put("include(UseD)\n"); script.put( "add_d_conditions(VERSION %s DEBUG %s)\n".format( info.buildSettings.versions.dup.join(" "), info.buildSettings.debugVersions.dup.join(" "), ) ); foreach(directory; info.buildSettings.importPaths) script.put("include_directories(%s)\n".format(directory.sanitizeSlashes)); if(addTarget) { script.put("add_%s(%s %s\n".format(targetType, name, libType)); foreach(file; info.buildSettings.sourceFiles) script.put(" %s\n".format(file.sanitizeSlashes)); script.put(")\n"); script.put( "target_link_libraries(%s %s %s)\n".format( name, (info.dependencies ~ info.linkDependencies).dup.stdsort.uniq.map!(s => sanitize(s)).join(" "), info.buildSettings.libs.dup.join(" ") ) ); script.put( `set_target_properties(%s PROPERTIES TEXT_INCLUDE_DIRECTORIES "%s")`.format( name, info.buildSettings.stringImportPaths.map!(s => sanitizeSlashes(s)).join(";") ) ~ "\n" ); } string filename = (projectRoot ~ "%s.cmake".format(name)).toNativeString; File file = File(filename, "w"); file.write(script.data); file.close; script.shrinkTo(0); scripts.put(filename); } if(!cmakeListsPath.existsFile) { logWarn("You must use a fork of CMake which has D support for these scripts to function properly."); logWarn("It is available at https://github.com/trentforkert/cmake"); logInfo("Generating default CMakeLists.txt"); script.put("cmake_minimum_required(VERSION 3.0)\n"); script.put("project(%s D)\n".format(m_project.rootPackage.name)); foreach(path; scripts.data) script.put("include(%s)\n".format(path)); File file = File(cmakeListsPath.toNativeString, "w"); file.write(script.data); file.close; } } } ///Transform a package name into a valid CMake target name. private string sanitize(string name) { return name.replace(":", "_"); } private string sanitizeSlashes(string path) { version(Windows) return path.replace("\\", "/"); else return path; } dub-1.19.0/source/dub/generators/generator.d000066400000000000000000000727601360435400500207460ustar00rootroot00000000000000/** Generator for project files Copyright: © 2012-2013 Matthias Dondorff, © 2013-2016 Sönke Ludwig License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Matthias Dondorff */ module dub.generators.generator; import dub.compilers.compiler; import dub.generators.cmake; import dub.generators.build; import dub.generators.sublimetext; import dub.generators.visuald; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import dub.package_; import dub.packagemanager; import dub.project; import std.algorithm : map, filter, canFind, balancedParens; import std.array : array; import std.array; import std.exception; import std.file; import std.string; /** Common interface for project generators/builders. */ class ProjectGenerator { /** Information about a single binary target. A binary target can either be an executable or a static/dynamic library. It consists of one or more packages. */ struct TargetInfo { /// The root package of this target Package pack; /// All packages compiled into this target Package[] packages; /// The configuration used for building the root package string config; /** Build settings used to build the target. The build settings include all sources of all contained packages. Depending on the specific generator implementation, it may be necessary to add any static or dynamic libraries generated for child targets ($(D linkDependencies)). */ BuildSettings buildSettings; /** List of all dependencies. This list includes dependencies that are not the root of a binary target. */ string[] dependencies; /** List of all binary dependencies. This list includes all dependencies that are the root of a binary target. */ string[] linkDependencies; } protected { Project m_project; NativePath m_tempTargetExecutablePath; } this(Project project) { m_project = project; } /** Performs the full generator process. */ final void generate(GeneratorSettings settings) { import dub.compilers.utils : enforceBuildRequirements; if (!settings.config.length) settings.config = m_project.getDefaultConfiguration(settings.platform); string[string] configs = m_project.getPackageConfigs(settings.platform, settings.config); TargetInfo[string] targets; foreach (pack; m_project.getTopologicalPackageList(true, null, configs)) { BuildSettings buildSettings; auto config = configs[pack.name]; buildSettings.processVars(m_project, pack, pack.getBuildSettings(settings.platform, config), settings, true); targets[pack.name] = TargetInfo(pack, [pack], config, buildSettings); prepareGeneration(pack, m_project, settings, buildSettings); } configurePackages(m_project.rootPackage, targets, settings); addBuildTypeSettings(targets, settings); foreach (ref t; targets.byValue) enforceBuildRequirements(t.buildSettings); generateTargets(settings, targets); foreach (pack; m_project.getTopologicalPackageList(true, null, configs)) { BuildSettings buildsettings; buildsettings.processVars(m_project, pack, pack.getBuildSettings(settings.platform, configs[pack.name]), settings, true); bool generate_binary = !(buildsettings.options & BuildOption.syntaxOnly); auto bs = &targets[m_project.rootPackage.name].buildSettings; auto targetPath = (m_tempTargetExecutablePath.empty) ? NativePath(bs.targetPath) : m_tempTargetExecutablePath; finalizeGeneration(pack, m_project, settings, buildsettings, targetPath, generate_binary); } performPostGenerateActions(settings, targets); } /** Overridden in derived classes to implement the actual generator functionality. The function should go through all targets recursively. The first target (which is guaranteed to be there) is $(D targets[m_project.rootPackage.name]). The recursive descent is then done using the $(D TargetInfo.linkDependencies) list. This method is also potentially responsible for running the pre and post build commands, while pre and post generate commands are already taken care of by the $(D generate) method. Params: settings = The generator settings used for this run targets = A map from package name to TargetInfo that contains all binary targets to be built. */ protected abstract void generateTargets(GeneratorSettings settings, in TargetInfo[string] targets); /** Overridable method to be invoked after the generator process has finished. An examples of functionality placed here is to run the application that has just been built. */ protected void performPostGenerateActions(GeneratorSettings settings, in TargetInfo[string] targets) {} /** Configure `rootPackage` and all of it's dependencies. 1. Merge versions, debugVersions, and inheritable build settings from dependents to their dependencies. 2. Define version identifiers Have_dependency_xyz for all direct dependencies of all packages. 3. Merge versions, debugVersions, and inheritable build settings from dependencies to their dependents, so that importer and importee are ABI compatible. This also transports all Have_dependency_xyz version identifiers to `rootPackage`. 4. Filter unused versions and debugVersions from all targets. The filters have previously been upwards inherited (3.) so that versions used in a dependency are also applied to all dependents. Note: The upwards inheritance is done at last so that siblings do not influence each other, also see https://github.com/dlang/dub/pull/1128. Note: Targets without output are integrated into their dependents and removed from `targets`. */ private void configurePackages(Package rootPackage, TargetInfo[string] targets, GeneratorSettings genSettings) { import std.algorithm : remove, sort; import std.range : repeat; auto roottarget = &targets[rootPackage.name]; // 0. do shallow configuration (not including dependencies) of all packages TargetType determineTargetType(const ref TargetInfo ti) { TargetType tt = ti.buildSettings.targetType; if (ti.pack is rootPackage) { if (tt == TargetType.autodetect || tt == TargetType.library) tt = TargetType.staticLibrary; } else { if (tt == TargetType.autodetect || tt == TargetType.library) tt = genSettings.combined ? TargetType.sourceLibrary : TargetType.staticLibrary; else if (tt == TargetType.dynamicLibrary) { logWarn("Dynamic libraries are not yet supported as dependencies - building as static library."); tt = TargetType.staticLibrary; } } if (tt != TargetType.none && tt != TargetType.sourceLibrary && ti.buildSettings.sourceFiles.empty) { logWarn(`Configuration '%s' of package %s contains no source files. Please add {"targetType": "none"} to its package description to avoid building it.`, ti.config, ti.pack.name); tt = TargetType.none; } return tt; } string[] mainSourceFiles; bool[string] hasOutput; foreach (ref ti; targets.byValue) { auto bs = &ti.buildSettings; // determine the actual target type bs.targetType = determineTargetType(ti); switch (bs.targetType) { case TargetType.none: // ignore any build settings for targetType none (only dependencies will be processed) *bs = BuildSettings.init; bs.targetType = TargetType.none; break; case TargetType.executable: break; case TargetType.dynamicLibrary: // set -fPIC for dynamic library builds ti.buildSettings.addOptions(BuildOption.pic); goto default; default: // remove any mainSourceFile from non-executable builds if (bs.mainSourceFile.length) { bs.sourceFiles = bs.sourceFiles.remove!(f => f == bs.mainSourceFile); mainSourceFiles ~= bs.mainSourceFile; } break; } bool generatesBinary = bs.targetType != TargetType.sourceLibrary && bs.targetType != TargetType.none; hasOutput[ti.pack.name] = generatesBinary || ti.pack is rootPackage; } // add main source files to root executable { auto bs = &roottarget.buildSettings; if (bs.targetType == TargetType.executable) bs.addSourceFiles(mainSourceFiles); } if (genSettings.filterVersions) foreach (ref ti; targets.byValue) inferVersionFilters(ti); // mark packages as visited (only used during upwards propagation) void[0][Package] visited; // collect all dependencies void collectDependencies(Package pack, ref TargetInfo ti, TargetInfo[string] targets, size_t level = 0) { // use `visited` here as pkgs cannot depend on themselves if (pack in visited) return; // transitive dependencies must be visited multiple times, see #1350 immutable transitive = !hasOutput[pack.name]; if (!transitive) visited[pack] = typeof(visited[pack]).init; auto bs = &ti.buildSettings; if (hasOutput[pack.name]) logDebug("%sConfiguring target %s (%s %s %s)", ' '.repeat(2 * level), pack.name, bs.targetType, bs.targetPath, bs.targetName); else logDebug("%sConfiguring target without output %s", ' '.repeat(2 * level), pack.name); // get specified dependencies, e.g. vibe-d ~0.8.1 auto deps = pack.getDependencies(targets[pack.name].config); logDebug("deps: %s -> %(%s, %)", pack.name, deps.byKey); foreach (depname; deps.keys.sort()) { auto depspec = deps[depname]; // get selected package for that dependency, e.g. vibe-d 0.8.2-beta.2 auto deppack = m_project.getDependency(depname, depspec.optional); if (deppack is null) continue; // optional and not selected // if dependency has no output if (!hasOutput[depname]) { // add itself ti.packages ~= deppack; // and it's transitive dependencies to current target collectDependencies(deppack, ti, targets, level + 1); continue; } auto depti = &targets[depname]; const depbs = &depti.buildSettings; if (depbs.targetType == TargetType.executable && ti.buildSettings.targetType != TargetType.none) continue; // add to (link) dependencies ti.dependencies ~= depname; ti.linkDependencies ~= depname; // recurse collectDependencies(deppack, *depti, targets, level + 1); // also recursively add all link dependencies of static libraries // preserve topological sorting of dependencies for correct link order if (depbs.targetType == TargetType.staticLibrary) ti.linkDependencies = ti.linkDependencies.filter!(d => !depti.linkDependencies.canFind(d)).array ~ depti.linkDependencies; } enforce(!(ti.buildSettings.targetType == TargetType.none && ti.dependencies.empty), "Package with target type \"none\" must have dependencies to build."); } collectDependencies(rootPackage, *roottarget, targets); visited.clear(); // 1. downwards inherits versions, debugVersions, and inheritable build settings static void configureDependencies(in ref TargetInfo ti, TargetInfo[string] targets, size_t level = 0) { // do not use `visited` here as dependencies must inherit // configurations from *all* of their parents logDebug("%sConfigure dependencies of %s, deps:%(%s, %)", ' '.repeat(2 * level), ti.pack.name, ti.dependencies); foreach (depname; ti.dependencies) { auto pti = &targets[depname]; mergeFromDependent(ti.buildSettings, pti.buildSettings); configureDependencies(*pti, targets, level + 1); } } configureDependencies(*roottarget, targets); // 2. add Have_dependency_xyz for all direct dependencies of a target // (includes incorporated non-target dependencies and their dependencies) foreach (ref ti; targets.byValue) { import std.range : chain; import dub.internal.utils : stripDlangSpecialChars; auto bs = &ti.buildSettings; auto pkgnames = ti.packages.map!(p => p.name).chain(ti.dependencies); bs.addVersions(pkgnames.map!(pn => "Have_" ~ stripDlangSpecialChars(pn)).array); } // 3. upwards inherit full build configurations (import paths, versions, debugVersions, versionFilters, importPaths, ...) void configureDependents(ref TargetInfo ti, TargetInfo[string] targets, size_t level = 0) { // use `visited` here as pkgs cannot depend on themselves if (ti.pack in visited) return; visited[ti.pack] = typeof(visited[ti.pack]).init; logDiagnostic("%sConfiguring dependent %s, deps:%(%s, %)", ' '.repeat(2 * level), ti.pack.name, ti.dependencies); // embedded non-binary dependencies foreach (deppack; ti.packages[1 .. $]) ti.buildSettings.add(targets[deppack.name].buildSettings); // binary dependencies foreach (depname; ti.dependencies) { auto pdepti = &targets[depname]; configureDependents(*pdepti, targets, level + 1); mergeFromDependency(pdepti.buildSettings, ti.buildSettings, genSettings.platform); } } configureDependents(*roottarget, targets); visited.clear(); // 4. Filter applicable version and debug version identifiers if (genSettings.filterVersions) { foreach (name, ref ti; targets) { import std.algorithm.sorting : partition; auto bs = &ti.buildSettings; auto filtered = bs.versions.partition!(v => bs.versionFilters.canFind(v)); logDebug("Filtering out unused versions for %s: %s", name, filtered); bs.versions = bs.versions[0 .. $ - filtered.length]; filtered = bs.debugVersions.partition!(v => bs.debugVersionFilters.canFind(v)); logDebug("Filtering out unused debug versions for %s: %s", name, filtered); bs.debugVersions = bs.debugVersions[0 .. $ - filtered.length]; } } // 5. override string import files in dependencies static void overrideStringImports(ref TargetInfo target, ref TargetInfo parent, TargetInfo[string] targets, string[] overrides) { // Since string import paths are inherited from dependencies in the // inheritance step above (step 3), it is guaranteed that all // following dependencies will not have string import paths either, // so we can skip the recursion here if (!target.buildSettings.stringImportPaths.length) return; // do not use visited here as string imports can be overridden by *any* parent // // special support for overriding string imports in parent packages // this is a candidate for deprecation, once an alternative approach // has been found bool any_override = false; // override string import files (used for up to date checking) foreach (ref f; target.buildSettings.stringImportFiles) { foreach (o; overrides) { NativePath op; if (f != o && NativePath(f).head == (op = NativePath(o)).head) { logDebug("string import %s overridden by %s", f, o); f = o; any_override = true; } } } // override string import paths by prepending to the list, in // case there is any overlapping file if (any_override) target.buildSettings.prependStringImportPaths(parent.buildSettings.stringImportPaths); // add all files to overrides for recursion overrides ~= target.buildSettings.stringImportFiles; // recursively override all dependencies with the accumulated files/paths foreach (depname; target.dependencies) overrideStringImports(targets[depname], target, targets, overrides); } // push string import paths/files down to all direct and indirect // dependencies, overriding their own foreach (depname; roottarget.dependencies) overrideStringImports(targets[depname], *roottarget, targets, roottarget.buildSettings.stringImportFiles); // remove targets without output foreach (name; targets.keys) { if (!hasOutput[name]) targets.remove(name); } } // infer applicable version identifiers private static void inferVersionFilters(ref TargetInfo ti) { import std.algorithm.searching : any; import std.file : timeLastModified; import std.path : extension; import std.range : chain; import std.regex : ctRegex, matchAll; import std.stdio : File; import std.datetime : Clock, SysTime, UTC; import dub.compilers.utils : isLinkerFile; import dub.internal.vibecompat.data.json : Json, JSONException; auto bs = &ti.buildSettings; // only infer if neither version filters are specified explicitly if (bs.versionFilters.length || bs.debugVersionFilters.length) { logDebug("Using specified versionFilters for %s: %s %s", ti.pack.name, bs.versionFilters, bs.debugVersionFilters); return; } // check all existing source files for version identifiers static immutable dexts = [".d", ".di"]; auto srcs = chain(bs.sourceFiles, bs.importFiles, bs.stringImportFiles) .filter!(f => dexts.canFind(f.extension)).filter!exists; // try to load cached filters first auto cache = ti.pack.metadataCache; try { auto cachedFilters = cache["versionFilters"]; if (cachedFilters.type != Json.Type.undefined) cachedFilters = cachedFilters[ti.config]; if (cachedFilters.type != Json.Type.undefined) { immutable mtime = SysTime.fromISOExtString(cachedFilters["mtime"].get!string); if (!srcs.any!(src => src.timeLastModified > mtime)) { auto versionFilters = cachedFilters["versions"][].map!(j => j.get!string).array; auto debugVersionFilters = cachedFilters["debugVersions"][].map!(j => j.get!string).array; logDebug("Using cached versionFilters for %s: %s %s", ti.pack.name, versionFilters, debugVersionFilters); bs.addVersionFilters(versionFilters); bs.addDebugVersionFilters(debugVersionFilters); return; } } } catch (JSONException e) { logWarn("Exception during loading invalid package cache %s.\n%s", ti.pack.path ~ ".dub/metadata_cache.json", e); } // use ctRegex for performance reasons, only small compile time increase enum verRE = ctRegex!`(?:^|\s)version\s*\(\s*([^\s]*?)\s*\)`; enum debVerRE = ctRegex!`(?:^|\s)debug\s*\(\s*([^\s]*?)\s*\)`; auto versionFilters = appender!(string[]); auto debugVersionFilters = appender!(string[]); foreach (file; srcs) { foreach (line; File(file).byLine) { foreach (m; line.matchAll(verRE)) if (!versionFilters.data.canFind(m[1])) versionFilters.put(m[1].idup); foreach (m; line.matchAll(debVerRE)) if (!debugVersionFilters.data.canFind(m[1])) debugVersionFilters.put(m[1].idup); } } logDebug("Using inferred versionFilters for %s: %s %s", ti.pack.name, versionFilters.data, debugVersionFilters.data); bs.addVersionFilters(versionFilters.data); bs.addDebugVersionFilters(debugVersionFilters.data); auto cachedFilters = cache["versionFilters"]; if (cachedFilters.type == Json.Type.undefined) cachedFilters = cache["versionFilters"] = [ti.config: Json.emptyObject]; cachedFilters[ti.config] = [ "mtime": Json(Clock.currTime(UTC()).toISOExtString), "versions": Json(versionFilters.data.map!Json.array), "debugVersions": Json(debugVersionFilters.data.map!Json.array), ]; ti.pack.metadataCache = cache; } private static void mergeFromDependent(in ref BuildSettings parent, ref BuildSettings child) { child.addVersions(parent.versions); child.addDebugVersions(parent.debugVersions); child.addOptions(BuildOptions(parent.options & inheritedBuildOptions)); } private static void mergeFromDependency(in ref BuildSettings child, ref BuildSettings parent, in ref BuildPlatform platform) { import dub.compilers.utils : isLinkerFile; parent.addDFlags(child.dflags); parent.addVersions(child.versions); parent.addDebugVersions(child.debugVersions); parent.addVersionFilters(child.versionFilters); parent.addDebugVersionFilters(child.debugVersionFilters); parent.addImportPaths(child.importPaths); parent.addStringImportPaths(child.stringImportPaths); // linking of static libraries is done by parent if (child.targetType == TargetType.staticLibrary) { parent.addSourceFiles(child.sourceFiles.filter!(f => isLinkerFile(platform, f)).array); parent.addLibs(child.libs); parent.addLFlags(child.lflags); } } // configure targets for build types such as release, or unittest-cov private void addBuildTypeSettings(TargetInfo[string] targets, in GeneratorSettings settings) { foreach (ref ti; targets.byValue) { ti.buildSettings.add(settings.buildSettings); // add build type settings and convert plain DFLAGS to build options m_project.addBuildTypeSettings(ti.buildSettings, settings, ti.pack is m_project.rootPackage); settings.compiler.extractBuildOptions(ti.buildSettings); auto tt = ti.buildSettings.targetType; enforce (tt != TargetType.sourceLibrary || ti.pack !is m_project.rootPackage || (ti.buildSettings.options & BuildOption.syntaxOnly), format("Main package must not have target type \"%s\". Cannot build.", tt)); } } } struct GeneratorSettings { BuildPlatform platform; Compiler compiler; string config; string buildType; BuildSettings buildSettings; BuildMode buildMode = BuildMode.separate; int targetExitStatus; bool combined; // compile all in one go instead of each dependency separately bool filterVersions; // only used for generator "build" bool run, force, direct, rdmd, tempBuild, parallelBuild; /// single file dub package bool single; string[] runArgs; void delegate(int status, string output) compileCallback; void delegate(int status, string output) linkCallback; void delegate(int status, string output) runCallback; } /** Determines the mode in which the compiler and linker are invoked. */ enum BuildMode { separate, /// Compile and link separately allAtOnce, /// Perform compile and link with a single compiler invocation singleFile, /// Compile each file separately //multipleObjects, /// Generate an object file per module //multipleObjectsPerModule, /// Use the -multiobj switch to generate multiple object files per module //compileOnly /// Do not invoke the linker (can be done using a post build command) } /** Creates a project generator of the given type for the specified project. */ ProjectGenerator createProjectGenerator(string generator_type, Project project) { assert(project !is null, "Project instance needed to create a generator."); generator_type = generator_type.toLower(); switch(generator_type) { default: throw new Exception("Unknown project generator: "~generator_type); case "build": logDebug("Creating build generator."); return new BuildGenerator(project); case "mono-d": throw new Exception("The Mono-D generator has been removed. Use Mono-D's built in DUB support instead."); case "visuald": logDebug("Creating VisualD generator."); return new VisualDGenerator(project); case "sublimetext": logDebug("Creating SublimeText generator."); return new SublimeTextGenerator(project); case "cmake": logDebug("Creating CMake generator."); return new CMakeGenerator(project); } } /** Runs pre-build commands and performs other required setup before project files are generated. */ private void prepareGeneration(in Package pack, in Project proj, in GeneratorSettings settings, in BuildSettings buildsettings) { if (buildsettings.preGenerateCommands.length && !isRecursiveInvocation(pack.name)) { logInfo("Running pre-generate commands for %s...", pack.name); runBuildCommands(buildsettings.preGenerateCommands, pack, proj, settings, buildsettings); } } /** Runs post-build commands and copies required files to the binary directory. */ private void finalizeGeneration(in Package pack, in Project proj, in GeneratorSettings settings, in BuildSettings buildsettings, NativePath target_path, bool generate_binary) { import std.path : globMatch; if (buildsettings.postGenerateCommands.length && !isRecursiveInvocation(pack.name)) { logInfo("Running post-generate commands for %s...", pack.name); runBuildCommands(buildsettings.postGenerateCommands, pack, proj, settings, buildsettings); } if (generate_binary) { if (!exists(buildsettings.targetPath)) mkdirRecurse(buildsettings.targetPath); if (buildsettings.copyFiles.length) { void copyFolderRec(NativePath folder, NativePath dstfolder) { mkdirRecurse(dstfolder.toNativeString()); foreach (de; iterateDirectory(folder.toNativeString())) { if (de.isDirectory) { copyFolderRec(folder ~ de.name, dstfolder ~ de.name); } else { try hardLinkFile(folder ~ de.name, dstfolder ~ de.name, true); catch (Exception e) { logWarn("Failed to copy file %s: %s", (folder ~ de.name).toNativeString(), e.msg); } } } } void tryCopyDir(string file) { auto src = NativePath(file); if (!src.absolute) src = pack.path ~ src; auto dst = target_path ~ NativePath(file).head; if (src == dst) { logDiagnostic("Skipping copy of %s (same source and destination)", file); return; } logDiagnostic(" %s to %s", src.toNativeString(), dst.toNativeString()); try { copyFolderRec(src, dst); } catch(Exception e) logWarn("Failed to copy %s to %s: %s", src.toNativeString(), dst.toNativeString(), e.msg); } void tryCopyFile(string file) { auto src = NativePath(file); if (!src.absolute) src = pack.path ~ src; auto dst = target_path ~ NativePath(file).head; if (src == dst) { logDiagnostic("Skipping copy of %s (same source and destination)", file); return; } logDiagnostic(" %s to %s", src.toNativeString(), dst.toNativeString()); try { hardLinkFile(src, dst, true); } catch(Exception e) logWarn("Failed to copy %s to %s: %s", src.toNativeString(), dst.toNativeString(), e.msg); } logInfo("Copying files for %s...", pack.name); string[] globs; foreach (f; buildsettings.copyFiles) { if (f.canFind("*", "?") || (f.canFind("{") && f.balancedParens('{', '}')) || (f.canFind("[") && f.balancedParens('[', ']'))) { globs ~= f; } else { if (f.isDir) tryCopyDir(f); else tryCopyFile(f); } } if (globs.length) // Search all files for glob matches { foreach (f; dirEntries(pack.path.toNativeString(), SpanMode.breadth)) { foreach (glob; globs) { if (f.name().globMatch(glob)) { if (f.isDir) tryCopyDir(f); else tryCopyFile(f); break; } } } } } } } /** Runs a list of build commands for a particular package. This function sets all DUB speficic environment variables and makes sure that recursive dub invocations are detected and don't result in infinite command execution loops. The latter could otherwise happen when a command runs "dub describe" or similar functionality. */ void runBuildCommands(in string[] commands, in Package pack, in Project proj, in GeneratorSettings settings, in BuildSettings build_settings) { import dub.internal.utils : getDUBExePath, runCommands; import std.conv : to, text; import std.process : environment, escapeShellFileName; string[string] env = environment.toAA(); // TODO: do more elaborate things here // TODO: escape/quote individual items appropriately env["DFLAGS"] = join(cast(string[])build_settings.dflags, " "); env["LFLAGS"] = join(cast(string[])build_settings.lflags," "); env["VERSIONS"] = join(cast(string[])build_settings.versions," "); env["LIBS"] = join(cast(string[])build_settings.libs," "); env["IMPORT_PATHS"] = join(cast(string[])build_settings.importPaths," "); env["STRING_IMPORT_PATHS"] = join(cast(string[])build_settings.stringImportPaths," "); env["DC"] = settings.platform.compilerBinary; env["DC_BASE"] = settings.platform.compiler; env["D_FRONTEND_VER"] = to!string(settings.platform.frontendVersion); env["DUB_EXE"] = getDUBExePath(settings.platform.compilerBinary); env["DUB_PLATFORM"] = join(cast(string[])settings.platform.platform," "); env["DUB_ARCH"] = join(cast(string[])settings.platform.architecture," "); env["DUB_TARGET_TYPE"] = to!string(build_settings.targetType); env["DUB_TARGET_PATH"] = build_settings.targetPath; env["DUB_TARGET_NAME"] = build_settings.targetName; env["DUB_TARGET_EXIT_STATUS"] = settings.targetExitStatus.text; env["DUB_WORKING_DIRECTORY"] = build_settings.workingDirectory; env["DUB_MAIN_SOURCE_FILE"] = build_settings.mainSourceFile; env["DUB_CONFIG"] = settings.config; env["DUB_BUILD_TYPE"] = settings.buildType; env["DUB_BUILD_MODE"] = to!string(settings.buildMode); env["DUB_PACKAGE"] = pack.name; env["DUB_PACKAGE_DIR"] = pack.path.toNativeString(); env["DUB_ROOT_PACKAGE"] = proj.rootPackage.name; env["DUB_ROOT_PACKAGE_DIR"] = proj.rootPackage.path.toNativeString(); env["DUB_PACKAGE_VERSION"] = pack.version_.toString(); env["DUB_COMBINED"] = settings.combined? "TRUE" : ""; env["DUB_RUN"] = settings.run? "TRUE" : ""; env["DUB_FORCE"] = settings.force? "TRUE" : ""; env["DUB_DIRECT"] = settings.direct? "TRUE" : ""; env["DUB_RDMD"] = settings.rdmd? "TRUE" : ""; env["DUB_TEMP_BUILD"] = settings.tempBuild? "TRUE" : ""; env["DUB_PARALLEL_BUILD"] = settings.parallelBuild? "TRUE" : ""; env["DUB_RUN_ARGS"] = (cast(string[])settings.runArgs).map!(escapeShellFileName).join(" "); auto depNames = proj.dependencies.map!((a) => a.name).array(); storeRecursiveInvokations(env, proj.rootPackage.name ~ depNames); runCommands(commands, env, pack.path().toString()); } private bool isRecursiveInvocation(string pack) { import std.algorithm : canFind, splitter; import std.process : environment; return environment .get("DUB_PACKAGES_USED", "") .splitter(",") .canFind(pack); } private void storeRecursiveInvokations(string[string] env, string[] packs) { import std.algorithm : canFind, splitter; import std.range : chain; import std.process : environment; env["DUB_PACKAGES_USED"] = environment .get("DUB_PACKAGES_USED", "") .splitter(",") .chain(packs) .join(","); } dub-1.19.0/source/dub/generators/sublimetext.d000066400000000000000000000063621360435400500213200ustar00rootroot00000000000000/** Generator for SublimeText project files Copyright: © 2014 Nicholas Londey License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Nicholas Londey */ module dub.generators.sublimetext; import dub.compilers.compiler; import dub.generators.generator; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; import dub.packagemanager; import dub.project; import std.algorithm; import std.array; import std.compiler; import std.file; import std.path; import std.range; import std.string; class SublimeTextGenerator : ProjectGenerator { this(Project project) { super(project); } override void generateTargets(GeneratorSettings settings, in TargetInfo[string] targets) { auto buildSettings = targets[m_project.name].buildSettings; logDebug("About to generate sublime project for %s.", m_project.rootPackage.name); auto root = Json([ "folders": targets.byValue.map!(f => targetFolderJson(f)).array.Json, "build_systems": buildSystems(settings.platform), "settings": [ "include_paths": buildSettings.importPaths.map!Json.array.Json ].Json, ]); auto jsonString = appender!string(); writePrettyJsonString(jsonString, root); string projectPath = m_project.name ~ ".sublime-project"; write(projectPath, jsonString.data); logInfo("Project '%s' generated.", projectPath); } } private Json targetFolderJson(in ProjectGenerator.TargetInfo target) { return [ "name": target.pack.basePackage.name.Json, "path": target.pack.basePackage.path.toNativeString.Json, "follow_symlinks": true.Json, "folder_exclude_patterns": [".dub"].map!Json.array.Json, ].Json; } private Json buildSystems(BuildPlatform buildPlatform, string workingDiretory = getcwd()) { static immutable BUILD_TYPES = [ //"plain", "debug", "release", "release-debug", "release-nobounds", //"unittest", "docs", "ddox", "profile", "profile-gc", "cov", "unittest-cov", "syntax" ]; string fileRegex; if (buildPlatform.frontendVersion >= 2066 && buildPlatform.compiler == "dmd") fileRegex = r"^(.+)\(([0-9]+)\,([0-9]+)\)\: (.*)$"; else fileRegex = r"^(.+)\(([0-9]+)\)\:() (.*)$"; auto arch = buildPlatform.architecture[0]; Json makeBuildSystem(string buildType) { return Json([ "name": "DUB build " ~ buildType.Json, "cmd": ["dub", "build", "--build=" ~ buildType, "--arch=" ~ arch, "--compiler="~buildPlatform.compilerBinary].map!Json.array.Json, "file_regex": fileRegex.Json, "working_dir": workingDiretory.Json, "variants": [ [ "name": "Run".Json, "cmd": ["dub", "run", "--build=" ~ buildType, "--arch=" ~ arch, "--compiler="~buildPlatform.compilerBinary].map!Json.array.Json, ].Json ].array.Json, ]); } auto buildSystems = BUILD_TYPES.map!makeBuildSystem.array; buildSystems ~= [ "name": "DUB test".Json, "cmd": ["dub", "test", "--arch=" ~ arch, "--compiler="~buildPlatform.compilerBinary].map!Json.array.Json, "file_regex": r"^(.+)\(([0-9]+)\)\:() (.*)$".Json, "working_dir": workingDiretory.Json, ].Json; return buildSystems.array.Json; } unittest { auto buildPlatform = BuildPlatform(); buildPlatform.architecture ~= "x86_64"; auto result = buildPlatform.buildSystems.toString; } dub-1.19.0/source/dub/generators/targetdescription.d000066400000000000000000000035601360435400500225020ustar00rootroot00000000000000/** Pseudo generator to output build descriptions. Copyright: © 2015 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.generators.targetdescription; import dub.compilers.buildsettings; import dub.compilers.compiler; import dub.description; import dub.generators.generator; import dub.internal.vibecompat.inet.path; import dub.project; class TargetDescriptionGenerator : ProjectGenerator { TargetDescription[] targetDescriptions; size_t[string] targetDescriptionLookup; this(Project project) { super(project); } protected override void generateTargets(GeneratorSettings settings, in TargetInfo[string] targets) { import std.algorithm : map; import std.array : array; auto configs = m_project.getPackageConfigs(settings.platform, settings.config); targetDescriptions.length = targets.length; size_t i = 0; bool[string] visited; void visitTargetRec(string target) { if (target in visited) return; visited[target] = true; auto ti = targets[target]; TargetDescription d; d.rootPackage = ti.pack.name; d.packages = ti.packages.map!(p => p.name).array; d.rootConfiguration = ti.config; d.buildSettings = ti.buildSettings.dup; d.dependencies = ti.dependencies.dup; d.linkDependencies = ti.linkDependencies.dup; // Add static library dependencies foreach (ld; ti.linkDependencies) { auto ltarget = targets[ld]; auto ltbs = ltarget.buildSettings; auto targetfil = (NativePath(ltbs.targetPath) ~ settings.compiler.getTargetFileName(ltbs, settings.platform)).toNativeString(); d.buildSettings.addLinkerFiles(targetfil); } targetDescriptionLookup[d.rootPackage] = i; targetDescriptions[i++] = d; foreach (dep; ti.dependencies) visitTargetRec(dep); } visitTargetRec(m_project.rootPackage.name); } } dub-1.19.0/source/dub/generators/visuald.d000066400000000000000000000507401360435400500204210ustar00rootroot00000000000000/** Generator for VisualD project files Copyright: © 2012-2013 Matthias Dondorff License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Matthias Dondorff */ module dub.generators.visuald; import dub.compilers.compiler; import dub.generators.generator; import dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.package_; import dub.packagemanager; import dub.project; import std.algorithm; import std.array; import std.conv; import std.exception; import std.format; import std.string : format; import std.uuid; // Dubbing is developing dub... //version = DUBBING; // TODO: handle pre/post build commands class VisualDGenerator : ProjectGenerator { private { PackageManager m_pkgMgr; string[string] m_projectUuids; } this(Project project) { super(project); m_pkgMgr = project.packageManager; } override void generateTargets(GeneratorSettings settings, in TargetInfo[string] targets) { logDebug("About to generate projects for %s, with %s direct dependencies.", m_project.rootPackage.name, m_project.rootPackage.getAllDependencies().length); generateProjectFiles(settings, targets); generateSolutionFile(settings, targets); } private { void generateSolutionFile(GeneratorSettings settings, in TargetInfo[string] targets) { auto ret = appender!(char[])(); auto configs = m_project.getPackageConfigs(settings.platform, settings.config); auto some_uuid = generateUUID(); // Solution header ret.put("Microsoft Visual Studio Solution File, Format Version 11.00\n"); ret.put("# Visual Studio 2010\n"); bool[string] visited; void generateSolutionEntry(string pack) { if (pack in visited) return; visited[pack] = true; auto ti = targets[pack]; auto uuid = guid(pack); ret.formattedWrite("Project(\"%s\") = \"%s\", \"%s\", \"%s\"\n", some_uuid, pack, projFileName(pack), uuid); if (ti.linkDependencies.length && ti.buildSettings.targetType != TargetType.staticLibrary) { ret.put("\tProjectSection(ProjectDependencies) = postProject\n"); foreach (d; ti.linkDependencies) if (!isHeaderOnlyPackage(d, targets)) { // TODO: clarify what "uuid = uuid" should mean ret.formattedWrite("\t\t%s = %s\n", guid(d), guid(d)); } ret.put("\tEndProjectSection\n"); } ret.put("EndProject\n"); foreach (d; ti.dependencies) generateSolutionEntry(d); } auto mainpack = m_project.rootPackage.name; generateSolutionEntry(mainpack); // Global section contains configurations ret.put("Global\n"); ret.put("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n"); ret.formattedWrite("\t\t%s|%s = %s|%s\n", settings.buildType, settings.platform.architecture[0].vsArchitecture, settings.buildType, settings.platform.architecture[0].vsArchitecture); ret.put("\tEndGlobalSection\n"); ret.put("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n"); const string[] sub = ["ActiveCfg", "Build.0"]; const string[] conf = [settings.buildType~"|"~settings.platform.architecture[0].vsArchitecture]; foreach (t; targets.byKey) foreach (c; conf) foreach (s; sub) formattedWrite(ret, "\t\t%s.%s.%s = %s\n", guid(t), c, s, c); // TODO: for all dependencies ret.put("\tEndGlobalSection\n"); ret.put("\tGlobalSection(SolutionProperties) = preSolution\n"); ret.put("\t\tHideSolutionNode = FALSE\n"); ret.put("\tEndGlobalSection\n"); ret.put("EndGlobal\n"); // Writing solution file logDebug("About to write to .sln file with %s bytes", to!string(ret.data.length)); auto sln = openFile(solutionFileName(), FileMode.createTrunc); scope(exit) sln.close(); sln.put(ret.data); sln.flush(); logInfo("Solution '%s' generated.", solutionFileName()); } void generateProjectFiles(GeneratorSettings settings, in TargetInfo[string] targets) { bool[string] visited; void performRec(string name) { if (name in visited) return; visited[name] = true; generateProjectFile(name, settings, targets); foreach (d; targets[name].dependencies) performRec(d); } performRec(m_project.rootPackage.name); } bool isHeaderOnlyPackage(string pack, in TargetInfo[string] targets) const { auto buildsettings = targets[pack].buildSettings; if (!buildsettings.sourceFiles.any!(f => f.endsWith(".d"))()) return true; return false; } void generateProjectFile(string packname, GeneratorSettings settings, in TargetInfo[string] targets) { import dub.compilers.utils : isLinkerFile; auto ret = appender!(char[])(); auto project_file_dir = m_project.rootPackage.path ~ projFileName(packname).parentPath; ret.put("\n"); ret.formattedWrite(" %s\n", guid(packname)); // Several configurations (debug, release, unittest) generateProjectConfiguration(ret, packname, settings.buildType, settings, targets); //generateProjectConfiguration(ret, packname, "release", settings, targets); //generateProjectConfiguration(ret, packname, "unittest", settings, targets); // Add all files auto files = targets[packname].buildSettings; SourceFile[string] sourceFiles; void addSourceFile(NativePath file_path, NativePath structure_path, bool build) { auto key = file_path.toString(); auto sf = sourceFiles.get(key, SourceFile.init); sf.filePath = file_path; if (!sf.build) { sf.build = build; sf.structurePath = structure_path; } sourceFiles[key] = sf; } void addFile(string s, bool build) { auto sp = NativePath(s); assert(sp.absolute, format("Source path in %s expected to be absolute: %s", packname, s)); //if( !sp.absolute ) sp = pack.path ~ sp; addSourceFile(sp.relativeTo(project_file_dir), determineStructurePath(sp, targets[packname]), build); } foreach (p; targets[packname].packages) if (!p.recipePath.empty) addFile(p.recipePath.toNativeString(), false); if (files.targetType == TargetType.staticLibrary) foreach(s; files.sourceFiles.filter!(s => !isLinkerFile(settings.platform, s))) addFile(s, true); else foreach(s; files.sourceFiles.filter!(s => !s.endsWith(".lib"))) addFile(s, true); foreach(s; files.importFiles) addFile(s, false); foreach(s; files.stringImportFiles) addFile(s, false); // Create folders and files ret.formattedWrite(" ", getPackageFileName(packname)); typeof(NativePath.init.head)[] lastFolder; foreach(source; sortedSources(sourceFiles.values)) { logDebug("source looking at %s", source.structurePath); auto cur = source.structurePath.parentPath.bySegment.array; if(lastFolder != cur) { size_t same = 0; foreach(idx; 0..min(lastFolder.length, cur.length)) if(lastFolder[idx] != cur[idx]) break; else same = idx+1; const decrease = lastFolder.length - min(lastFolder.length, same); const increase = cur.length - min(cur.length, same); foreach(unused; 0..decrease) ret.put("\n "); foreach(idx; 0..increase) ret.formattedWrite("\n ", cur[same + idx].name); lastFolder = cur; } ret.formattedWrite("\n ", source.build ? "" : "tool=\"None\" ", source.filePath.toNativeString()); } // Finalize all open folders foreach(unused; 0..lastFolder.length) ret.put("\n "); ret.put("\n \n"); logDebug("About to write to '%s.visualdproj' file %s bytes", getPackageFileName(packname), ret.data.length); auto proj = openFile(projFileName(packname), FileMode.createTrunc); scope(exit) proj.close(); proj.put(ret.data); proj.flush(); } void generateProjectConfiguration(Appender!(char[]) ret, string pack, string type, GeneratorSettings settings, in TargetInfo[string] targets) { auto project_file_dir = m_project.rootPackage.path ~ projFileName(pack).parentPath; auto buildsettings = targets[pack].buildSettings.dup; string[] getSettings(string setting)(){ return __traits(getMember, buildsettings, setting); } string[] getPathSettings(string setting)() { auto settings = getSettings!setting(); auto ret = new string[settings.length]; foreach (i; 0 .. settings.length) { // \" is interpreted as an escaped " by cmd.exe, so we need to avoid that auto p = NativePath(settings[i]).relativeTo(project_file_dir); p.endsWithSlash = false; ret[i] = '"' ~ p.toNativeString() ~ '"'; } return ret; } foreach(architecture; settings.platform.architecture) { auto arch = architecture.vsArchitecture; ret.formattedWrite(" \n", to!string(type), arch); // debug and optimize setting ret.formattedWrite(" %s\n", buildsettings.options & BuildOption.debugInfo ? "1" : "0"); ret.formattedWrite(" %s\n", buildsettings.options & BuildOption.optimize ? "1" : "0"); ret.formattedWrite(" %s\n", buildsettings.options & BuildOption.inline ? "1" : "0"); ret.formattedWrite(" %s\n", buildsettings.options & BuildOption.releaseMode ? "1" : "0"); // Lib or exe? enum { Executable = 0, StaticLib = 1, DynamicLib = 2 } int output_type = StaticLib; // library string output_ext = "lib"; if (buildsettings.targetType == TargetType.executable) { output_type = Executable; output_ext = "exe"; } else if (buildsettings.targetType == TargetType.dynamicLibrary) { output_type = DynamicLib; output_ext = "dll"; } auto bin_path = pack == m_project.rootPackage.name ? NativePath(buildsettings.targetPath) : NativePath("lib/"); bin_path.endsWithSlash = true; ret.formattedWrite(" %s\n", output_type); ret.formattedWrite(" %s%s.%s\n", bin_path.toNativeString(), buildsettings.targetName, output_ext); // include paths and string imports string imports = join(getPathSettings!"importPaths"(), " "); string stringImports = join(getPathSettings!"stringImportPaths"(), " "); ret.formattedWrite(" %s\n", imports); ret.formattedWrite(" %s\n", stringImports); ret.formattedWrite(" %s\n", "$(DMDInstallDir)windows\\bin\\dmd.exe"); // FIXME: use the actually selected compiler! ret.formattedWrite(" %s\n", getSettings!"dflags"().join(" ")); // Add version identifiers string versions = join(getSettings!"versions"(), " "); ret.formattedWrite(" %s\n", versions); // Add libraries, system libs need to be suffixed by ".lib". string linkLibs = join(map!(a => a~".lib")(getSettings!"libs"()), " "); string addLinkFiles = join(getSettings!"sourceFiles"().filter!(s => s.endsWith(".lib"))(), " "); if (arch == "x86") addLinkFiles ~= " phobos.lib"; if (output_type != StaticLib) ret.formattedWrite(" %s %s\n", linkLibs, addLinkFiles); // Unittests ret.formattedWrite(" %s\n", buildsettings.options & BuildOption.unittests ? "1" : "0"); // compute directory for intermediate files (need dummy/ because of how -op determines the resulting path) size_t ndummy = 0; foreach (f; buildsettings.sourceFiles) { auto rpath = NativePath(f).relativeTo(project_file_dir); size_t nd = 0; foreach (s; rpath.bySegment) if (s == "..") nd++; if (nd > ndummy) ndummy = nd; } string intersubdir = replicate("dummy/", ndummy) ~ getPackageFileName(pack); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); int singlefilemode; final switch (settings.buildMode) with (BuildMode) { case separate: singlefilemode = 2; break; case allAtOnce: singlefilemode = 0; break; case singleFile: singlefilemode = 1; break; //case compileOnly: singlefilemode = 3; break; } ret.formattedWrite(" %s\n", singlefilemode); ret.formattedWrite(" %s", buildsettings.dflags.canFind("-m32mscoff") ? "1" : "0"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.formattedWrite(" %s\n", buildsettings.options & BuildOption.verbose ? "1" : "0"); ret.put(" 0\n"); ret.put(" 0\n"); ret.formattedWrite(" %s\n", arch == "x64" ? 1 : 0); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.formattedWrite(" %s\n", buildsettings.options & BuildOption.noBoundsCheck ? "1" : "0"); ret.put(" 0\n"); ret.put(" 1\n"); ret.formattedWrite(" %s\n", buildsettings.options & BuildOption.warningsAsErrors ? "1" : "0"); ret.formattedWrite(" %s\n", buildsettings.options & BuildOption.warnings ? "1" : "0"); ret.formattedWrite(" %s\n", buildsettings.options & BuildOption.property ? "1" : "0"); ret.formattedWrite(" %s\n", buildsettings.options & BuildOption.alwaysStackFrame ? "1" : "0"); ret.put(" 0\n"); ret.formattedWrite(" %s\n", buildsettings.options & BuildOption.coverage ? "1" : "0"); ret.put(" 0\n"); ret.put(" 2\n"); ret.formattedWrite(" %s\n", buildsettings.options & BuildOption.ignoreUnknownPragmas ? "1" : "0"); ret.formattedWrite(" %s\n", settings.compiler.name == "ldc" ? 2 : settings.compiler.name == "gdc" ? 1 : 0); ret.formattedWrite(" 0\n"); ret.formattedWrite(" %s\n", bin_path.toNativeString()); ret.formattedWrite(" obj/%s/%s\n", to!string(type), intersubdir); ret.put(" \n"); ret.put(" \n"); ret.put(" 0\n"); ret.put(" \n"); ret.put(" \n"); ret.put(" \n"); ret.put(" \n"); ret.put(" 0\n"); ret.put(" \n"); ret.put(" \n"); ret.put(" 1\n"); ret.put(" $(IntDir)\\$(TargetName).json\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" \n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" \n"); ret.put(" \n"); ret.put(" \n"); ret.put(" 0\n"); ret.put(" \n"); ret.put(" 1\n"); ret.put(" $(VisualDInstallDir)cv2pdb\\cv2pdb.exe\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" 0\n"); ret.put(" \n"); ret.put(" \n"); ret.put(" \n"); ret.put(" \n"); ret.put(" \n"); ret.put(" \n"); auto wdir = NativePath(buildsettings.workingDirectory); if (!wdir.absolute) wdir = m_project.rootPackage.path ~ wdir; ret.formattedWrite(" %s\n", wdir.relativeTo(project_file_dir).toNativeString()); ret.put(" \n"); ret.put(" \n"); ret.put(" *.obj;*.cmd;*.build;*.dep\n"); ret.put(" \n"); } // foreach(architecture) } void performOnDependencies(const Package main, string[string] configs, void delegate(const Package pack) op) { foreach (p; m_project.getTopologicalPackageList(false, main, configs)) { if (p is main) continue; op(p); } } string generateUUID() const { import std.string; return "{" ~ toUpper(randomUUID().toString()) ~ "}"; } string guid(string projectName) { if(projectName !in m_projectUuids) m_projectUuids[projectName] = generateUUID(); return m_projectUuids[projectName]; } auto solutionFileName() const { version(DUBBING) return getPackageFileName(m_project.rootPackage) ~ ".dubbed.sln"; else return getPackageFileName(m_project.rootPackage.name) ~ ".sln"; } NativePath projFileName(string pack) const { auto basepath = NativePath(".dub/"); version(DUBBING) return basepath ~ (getPackageFileName(pack) ~ ".dubbed.visualdproj"); else return basepath ~ (getPackageFileName(pack) ~ ".visualdproj"); } } // TODO: nice folders private struct SourceFile { NativePath structurePath; NativePath filePath; bool build; size_t toHash() const nothrow @trusted { return structurePath.toHash() ^ filePath.toHash() ^ (build * 0x1f3e7b2c); } int opCmp(ref const SourceFile rhs) const { return sortOrder(this, rhs); } // "a < b" for folder structures (deepest folder first, else lexical) private final static int sortOrder(ref const SourceFile a, ref const SourceFile b) { assert(!a.structurePath.empty); assert(!b.structurePath.empty); static if (is(typeof(a.structurePath.nodes))) { // vibe.d < 0.8.2 auto as = a.structurePath.nodes; auto bs = b.structurePath.nodes; } else { auto as = a.structurePath.bySegment.array; auto bs = b.structurePath.bySegment.array; } // Check for different folders, compare folders only (omit last one). for(uint idx=0; idx bs.length? -1 : 1; } else { // Both paths indicate files in the same directory, use lexical // ordering for those. return as[$-1].name.cmp(bs[$-1].name); } } } private auto sortedSources(SourceFile[] sources) { return sort(sources); } unittest { SourceFile[] sfs = [ { NativePath("b/file.d"), NativePath("") }, { NativePath("b/b/fileA.d"), NativePath("") }, { NativePath("a/file.d"), NativePath("") }, { NativePath("b/b/fileB.d"), NativePath("") }, { NativePath("b/b/b/fileA.d"), NativePath("") }, { NativePath("b/c/fileA.d"), NativePath("") }, ]; auto sorted = sort(sfs); SourceFile[] sortedSfs; foreach(sr; sorted) sortedSfs ~= sr; assert(sortedSfs[0].structurePath == NativePath("a/file.d"), "1"); assert(sortedSfs[1].structurePath == NativePath("b/b/b/fileA.d"), "2"); assert(sortedSfs[2].structurePath == NativePath("b/b/fileA.d"), "3"); assert(sortedSfs[3].structurePath == NativePath("b/b/fileB.d"), "4"); assert(sortedSfs[4].structurePath == NativePath("b/c/fileA.d"), "5"); assert(sortedSfs[5].structurePath == NativePath("b/file.d"), "6"); } } private NativePath determineStructurePath(NativePath file_path, in ProjectGenerator.TargetInfo target) { foreach (p; target.packages) { if (file_path.startsWith(p.path)) return NativePath(getPackageFileName(p.name)) ~ file_path.relativeTo(p.path); } return NativePath("misc/") ~ file_path.head; } private string getPackageFileName(string pack) { return pack.replace(":", "_"); } private @property string vsArchitecture(string architecture) { switch(architecture) { default: logWarn("Unsupported platform('%s'), defaulting to x86", architecture); goto case; case "x86", "x86_mscoff": return "Win32"; case "x86_64": return "x64"; } } dub-1.19.0/source/dub/init.d000066400000000000000000000141271360435400500155430ustar00rootroot00000000000000/** Package skeleton initialization code. Copyright: © 2013-2016 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.init; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.package_ : PackageFormat, packageInfoFiles, defaultPackageFilename; import dub.recipe.packagerecipe; import dub.dependency; import std.exception; import std.file; import std.format; import std.process; import std.string; /** Initializes a new package in the given directory. The given `root_path` will be checked for any of the files that will be created by this function. If any exist, an exception will be thrown before altering the directory. Params: root_path = Directory in which to create the new package. If the directory doesn't exist, a new one will be created. deps = A set of extra dependencies to add to the package recipe. The associative array is expected to map from package name to package version. type = The type of package skeleton to create. Can currently be "minimal", "vibe.d" or "deimos" recipe_callback = Optional callback that can be used to customize the package recipe and the file format used to store it prior to writing it to disk. */ void initPackage(NativePath root_path, string[string] deps, string type, PackageFormat format, scope RecipeCallback recipe_callback = null) { import std.conv : to; import dub.recipe.io : writePackageRecipe; void enforceDoesNotExist(string filename) { enforce(!existsFile(root_path ~ filename), "The target directory already contains a '%s' %s. Aborting." .format(filename, filename.isDir ? "directory" : "file")); } string username = getUserName(); PackageRecipe p; p.name = root_path.head.name.toLower(); p.authors ~= username; p.license = "proprietary"; foreach (pack, v; deps) { import std.ascii : isDigit; p.buildSettings.dependencies[pack] = Dependency(v); } //Check to see if a target directory needs to be created if (!root_path.empty) { if (!existsFile(root_path)) createDirectory(root_path); } //Make sure we do not overwrite anything accidentally foreach (fil; packageInfoFiles) enforceDoesNotExist(fil.filename); auto files = ["source/", "views/", "public/", "dub.json"]; foreach (fil; files) enforceDoesNotExist(fil); void processRecipe() { if (recipe_callback) recipe_callback(p, format); } switch (type) { default: break; case "minimal": initMinimalPackage(root_path, p, &processRecipe); break; case "vibe.d": initVibeDPackage(root_path, p, &processRecipe); break; case "deimos": initDeimosPackage(root_path, p, &processRecipe); break; } writePackageRecipe(root_path ~ ("dub."~format.to!string), p); writeGitignore(root_path, p.name); } alias RecipeCallback = void delegate(ref PackageRecipe, ref PackageFormat); private void initMinimalPackage(NativePath root_path, ref PackageRecipe p, scope void delegate() pre_write_callback) { p.description = "A minimal D application."; pre_write_callback(); createDirectory(root_path ~ "source"); write((root_path ~ "source/app.d").toNativeString(), q{import std.stdio; void main() { writeln("Edit source/app.d to start your project."); } }); } private void initVibeDPackage(NativePath root_path, ref PackageRecipe p, scope void delegate() pre_write_callback) { if ("vibe-d" !in p.buildSettings.dependencies) p.buildSettings.dependencies["vibe-d"] = Dependency("~>0.8.2"); p.description = "A simple vibe.d server application."; pre_write_callback(); createDirectory(root_path ~ "source"); createDirectory(root_path ~ "views"); createDirectory(root_path ~ "public"); write((root_path ~ "source/app.d").toNativeString(), q{import vibe.vibe; void main() { auto settings = new HTTPServerSettings; settings.port = 8080; settings.bindAddresses = ["::1", "127.0.0.1"]; listenHTTP(settings, &hello); logInfo("Please open http://127.0.0.1:8080/ in your browser."); runApplication(); } void hello(HTTPServerRequest req, HTTPServerResponse res) { res.writeBody("Hello, World!"); } }); } private void initDeimosPackage(NativePath root_path, ref PackageRecipe p, scope void delegate() pre_write_callback) { import dub.compilers.buildsettings : TargetType; p.description = format("Deimos Bindings for "~p.name~"."); p.buildSettings.importPaths[""] ~= "."; p.buildSettings.targetType = TargetType.sourceLibrary; pre_write_callback(); createDirectory(root_path ~ "C"); createDirectory(root_path ~ "deimos"); } /** * Write the `.gitignore` file to the directory, if it does not already exists * * As `dub` is often used with `git`, adding a `.gitignore` is a nice touch for * most users. However, this file is not mandatory for `dub` to do its job, * so we do not depend on the content. * One important use case we need to support is people running `dub init` on * a Github-initialized repository. Those might already contain a `.gitignore` * (and a README and a LICENSE), thus we should not bail out if the file already * exists, just ignore it. * * Params: * root_path = The path to the directory hosting the project * pkg_name = Name of the package, to generate a list of binaries to ignore */ private void writeGitignore(NativePath root_path, const(char)[] pkg_name) { auto full_path = (root_path ~ ".gitignore").toNativeString(); if (existsFile(full_path)) return; write(full_path, q"{.dub docs.json __dummy.html docs/ /%1$s %1$s.so %1$s.dylib %1$s.dll %1$s.a %1$s.lib %1$s-test-* *.exe *.o *.obj *.lst }".format(pkg_name)); } private string getUserName() { version (Windows) return environment.get("USERNAME", "Peter Parker"); else version (Posix) { import core.sys.posix.pwd, core.sys.posix.unistd, core.stdc.string : strlen; import std.algorithm : splitter; // Bionic doesn't have pw_gecos on ARM version(CRuntime_Bionic) {} else if (auto pw = getpwuid(getuid)) { auto uinfo = pw.pw_gecos[0 .. strlen(pw.pw_gecos)].splitter(','); if (!uinfo.empty && uinfo.front.length) return uinfo.front.idup; } return environment.get("USER", "Peter Parker"); } else static assert(0); } dub-1.19.0/source/dub/internal/000077500000000000000000000000001360435400500162425ustar00rootroot00000000000000dub-1.19.0/source/dub/internal/git.d000066400000000000000000000061561360435400500172020ustar00rootroot00000000000000module dub.internal.git; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import std.file; import std.string; version (Windows) { import dub.internal.vibecompat.data.json; string determineVersionWithGit(NativePath path) { // On Windows, which is slow at running external processes, // cache the version numbers that are determined using // git to speed up the initialization phase. import dub.internal.utils : jsonFromFile; // quickly determine head commit without invoking git string head_commit; auto hpath = (path ~ ".git/HEAD").toNativeString(); if (exists(hpath)) { auto head_ref = readText(hpath).strip(); if (head_ref.startsWith("ref: ")) { auto rpath = (path ~ (".git/"~head_ref[5 .. $])).toNativeString(); if (exists(rpath)) head_commit = readText(rpath).strip(); } } // return the last determined version for that commit // not that this is not always correct, most notably when // a tag gets added/removed/changed and changes the outcome // of the full version detection computation auto vcachepath = path ~ ".dub/version.json"; if (existsFile(vcachepath)) { auto ver = jsonFromFile(vcachepath); if (head_commit == ver["commit"].opt!string) return ver["version"].get!string; } // if no cache file or the HEAD commit changed, perform full detection auto ret = determineVersionWithGitTool(path); // update version cache file if (head_commit.length) { import dub.internal.utils : atomicWriteJsonFile; if (!existsFile(path ~".dub")) createDirectory(path ~ ".dub"); atomicWriteJsonFile(vcachepath, Json(["commit": Json(head_commit), "version": Json(ret)])); } return ret; } } else { string determineVersionWithGit(NativePath path) { return determineVersionWithGitTool(path); } } // determines the version of a package that is stored in a Git working copy // by invoking the "git" executable private string determineVersionWithGitTool(NativePath path) { import dub.semver; import std.algorithm : canFind; import std.conv : to; import std.process; auto git_dir = path ~ ".git"; if (!existsFile(git_dir) || !isDir(git_dir.toNativeString)) return null; auto git_dir_param = "--git-dir=" ~ git_dir.toNativeString(); static string exec(scope string[] params...) { auto ret = executeShell(escapeShellCommand(params)); if (ret.status == 0) return ret.output.strip; logDebug("'%s' failed with exit code %s: %s", params.join(" "), ret.status, ret.output.strip); return null; } auto tag = exec("git", git_dir_param, "describe", "--long", "--tags"); if (tag !is null) { auto parts = tag.split("-"); auto commit = parts[$-1]; auto num = parts[$-2].to!int; tag = parts[0 .. $-2].join("-"); if (tag.startsWith("v") && isValidVersion(tag[1 .. $])) { if (num == 0) return tag[1 .. $]; else if (tag.canFind("+")) return format("%s.commit.%s.%s", tag[1 .. $], num, commit); else return format("%s+commit.%s.%s", tag[1 .. $], num, commit); } } auto branch = exec("git", git_dir_param, "rev-parse", "--abbrev-ref", "HEAD"); if (branch !is null) { if (branch != "HEAD") return "~" ~ branch; } return null; } dub-1.19.0/source/dub/internal/libInputVisitor.d000066400000000000000000000035341360435400500215620ustar00rootroot00000000000000module dub.internal.libInputVisitor; version (Have_libInputVisitor) public import libInputVisitor; else: /++ Copyright (C) 2012 Nick Sabalausky This program is free software. It comes without any warranty, to the extent permitted by applicable law. You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2, as published by Sam Hocevar. See http://www.wtfpl.net/ for more details. DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE Version 2, December 2004 Copyright (C) 2004 Sam Hocevar Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed. DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. You just DO WHAT THE FUCK YOU WANT TO. +/ /++ Should work with DMD 2.059 and up For more info on this, see: http://semitwist.com/articles/article/view/combine-coroutines-and-input-ranges-for-dead-simple-d-iteration +/ import core.thread; class InputVisitor(Obj, Elem) : Fiber { bool started = false; Obj obj; this(Obj obj) { this.obj = obj; super(&run); } private void run() { obj.visit(this); } private void ensureStarted() { if(!started) { call(); started = true; } } // Member 'front' must be a function due to DMD Issue #5403 private Elem _front; @property Elem front() { ensureStarted(); return _front; } void popFront() { ensureStarted(); call(); } @property bool empty() { ensureStarted(); return state == Fiber.State.TERM; } void yield(Elem elem) { _front = elem; Fiber.yield(); } } template inputVisitor(Elem) { @property InputVisitor!(Obj, Elem) inputVisitor(Obj)(Obj obj) { return new InputVisitor!(Obj, Elem)(obj); } } dub-1.19.0/source/dub/internal/sdlang/000077500000000000000000000000001360435400500175125ustar00rootroot00000000000000dub-1.19.0/source/dub/internal/sdlang/ast.d000066400000000000000000001467671360435400500204730ustar00rootroot00000000000000// SDLang-D // Written in the D programming language. module dub.internal.sdlang.ast; version (Have_sdlang_d) public import sdlang.ast; else: import std.algorithm; import std.array; import std.conv; import std.range; import std.string; version(sdlangUnittest) version(unittest) { import std.stdio; import std.exception; } import dub.internal.sdlang.exception; import dub.internal.sdlang.token; import dub.internal.sdlang.util; class Attribute { Value value; Location location; private Tag _parent; /// Get parent tag. To set a parent, attach this Attribute to its intended /// parent tag by calling 'Tag.add(...)', or by passing it to /// the parent tag's constructor. @property Tag parent() { return _parent; } private string _namespace; @property string namespace() { return _namespace; } /// Not particularly efficient, but it works. @property void namespace(string value) { if(_parent && _namespace != value) { // Remove auto saveParent = _parent; if(_parent) this.remove(); // Change namespace _namespace = value; // Re-add if(saveParent) saveParent.add(this); } else _namespace = value; } private string _name; /// Not including namespace. Use 'fullName' if you want the namespace included. @property string name() { return _name; } /// Not the most efficient, but it works. @property void name(string value) { if(_parent && _name != value) { _parent.updateId++; void removeFromGroupedLookup(string ns) { // Remove from _parent._attributes[ns] auto sameNameAttrs = _parent._attributes[ns][_name]; auto targetIndex = sameNameAttrs.countUntil(this); _parent._attributes[ns][_name].removeIndex(targetIndex); } // Remove from _parent._tags removeFromGroupedLookup(_namespace); removeFromGroupedLookup("*"); // Change name _name = value; // Add to new locations in _parent._attributes _parent._attributes[_namespace][_name] ~= this; _parent._attributes["*"][_name] ~= this; } else _name = value; } @property string fullName() { return _namespace==""? _name : text(_namespace, ":", _name); } this(string namespace, string name, Value value, Location location = Location(0, 0, 0)) { this._namespace = namespace; this._name = name; this.location = location; this.value = value; } this(string name, Value value, Location location = Location(0, 0, 0)) { this._namespace = ""; this._name = name; this.location = location; this.value = value; } /// Removes 'this' from its parent, if any. Returns 'this' for chaining. /// Inefficient ATM, but it works. Attribute remove() { if(!_parent) return this; void removeFromGroupedLookup(string ns) { // Remove from _parent._attributes[ns] auto sameNameAttrs = _parent._attributes[ns][_name]; auto targetIndex = sameNameAttrs.countUntil(this); _parent._attributes[ns][_name].removeIndex(targetIndex); } // Remove from _parent._attributes removeFromGroupedLookup(_namespace); removeFromGroupedLookup("*"); // Remove from _parent.allAttributes auto allAttrsIndex = _parent.allAttributes.countUntil(this); _parent.allAttributes.removeIndex(allAttrsIndex); // Remove from _parent.attributeIndicies auto sameNamespaceAttrs = _parent.attributeIndicies[_namespace]; auto attrIndiciesIndex = sameNamespaceAttrs.countUntil(allAttrsIndex); _parent.attributeIndicies[_namespace].removeIndex(attrIndiciesIndex); // Fixup other indicies foreach(ns, ref nsAttrIndicies; _parent.attributeIndicies) foreach(k, ref v; nsAttrIndicies) if(v > allAttrsIndex) v--; _parent.removeNamespaceIfEmpty(_namespace); _parent.updateId++; _parent = null; return this; } override bool opEquals(Object o) { auto a = cast(Attribute)o; if(!a) return false; return _namespace == a._namespace && _name == a._name && value == a.value; } string toSDLString()() { Appender!string sink; this.toSDLString(sink); return sink.data; } void toSDLString(Sink)(ref Sink sink) if(isOutputRange!(Sink,char)) { if(_namespace != "") { sink.put(_namespace); sink.put(':'); } sink.put(_name); sink.put('='); value.toSDLString(sink); } } class Tag { Location location; Value[] values; private Tag _parent; /// Get parent tag. To set a parent, attach this Tag to its intended /// parent tag by calling 'Tag.add(...)', or by passing it to /// the parent tag's constructor. @property Tag parent() { return _parent; } private string _namespace; @property string namespace() { return _namespace; } /// Not particularly efficient, but it works. @property void namespace(string value) { if(_parent && _namespace != value) { // Remove auto saveParent = _parent; if(_parent) this.remove(); // Change namespace _namespace = value; // Re-add if(saveParent) saveParent.add(this); } else _namespace = value; } private string _name; /// Not including namespace. Use 'fullName' if you want the namespace included. @property string name() { return _name; } /// Not the most efficient, but it works. @property void name(string value) { if(_parent && _name != value) { _parent.updateId++; void removeFromGroupedLookup(string ns) { // Remove from _parent._tags[ns] auto sameNameTags = _parent._tags[ns][_name]; auto targetIndex = sameNameTags.countUntil(this); _parent._tags[ns][_name].removeIndex(targetIndex); } // Remove from _parent._tags removeFromGroupedLookup(_namespace); removeFromGroupedLookup("*"); // Change name _name = value; // Add to new locations in _parent._tags _parent._tags[_namespace][_name] ~= this; _parent._tags["*"][_name] ~= this; } else _name = value; } /// This tag's name, including namespace if one exists. @property string fullName() { return _namespace==""? _name : text(_namespace, ":", _name); } // Tracks dirtiness. This is incremented every time a change is made which // could invalidate existing ranges. This way, the ranges can detect when // they've been invalidated. private size_t updateId=0; this(Tag parent = null) { if(parent) parent.add(this); } this( string namespace, string name, Value[] values=null, Attribute[] attributes=null, Tag[] children=null ) { this(null, namespace, name, values, attributes, children); } this( Tag parent, string namespace, string name, Value[] values=null, Attribute[] attributes=null, Tag[] children=null ) { this._namespace = namespace; this._name = name; if(parent) parent.add(this); this.values = values; this.add(attributes); this.add(children); } private Attribute[] allAttributes; // In same order as specified in SDL file. private Tag[] allTags; // In same order as specified in SDL file. private string[] allNamespaces; // In same order as specified in SDL file. private size_t[][string] attributeIndicies; // allAttributes[ attributes[namespace][i] ] private size_t[][string] tagIndicies; // allTags[ tags[namespace][i] ] private Attribute[][string][string] _attributes; // attributes[namespace or "*"][name][i] private Tag[][string][string] _tags; // tags[namespace or "*"][name][i] /// Adds a Value, Attribute, Tag (or array of such) as a member/child of this Tag. /// Returns 'this' for chaining. /// Throws 'SDLangValidationException' if trying to add an Attribute or Tag /// that already has a parent. Tag add(Value val) { values ~= val; updateId++; return this; } ///ditto Tag add(Value[] vals) { foreach(val; vals) add(val); return this; } ///ditto Tag add(Attribute attr) { if(attr._parent) { throw new SDLangValidationException( "Attribute is already attached to a parent tag. "~ "Use Attribute.remove() before adding it to another tag." ); } if(!allNamespaces.canFind(attr._namespace)) allNamespaces ~= attr._namespace; attr._parent = this; allAttributes ~= attr; attributeIndicies[attr._namespace] ~= allAttributes.length-1; _attributes[attr._namespace][attr._name] ~= attr; _attributes["*"] [attr._name] ~= attr; updateId++; return this; } ///ditto Tag add(Attribute[] attrs) { foreach(attr; attrs) add(attr); return this; } ///ditto Tag add(Tag tag) { if(tag._parent) { throw new SDLangValidationException( "Tag is already attached to a parent tag. "~ "Use Tag.remove() before adding it to another tag." ); } if(!allNamespaces.canFind(tag._namespace)) allNamespaces ~= tag._namespace; tag._parent = this; allTags ~= tag; tagIndicies[tag._namespace] ~= allTags.length-1; _tags[tag._namespace][tag._name] ~= tag; _tags["*"] [tag._name] ~= tag; updateId++; return this; } ///ditto Tag add(Tag[] tags) { foreach(tag; tags) add(tag); return this; } /// Removes 'this' from its parent, if any. Returns 'this' for chaining. /// Inefficient ATM, but it works. Tag remove() { if(!_parent) return this; void removeFromGroupedLookup(string ns) { // Remove from _parent._tags[ns] auto sameNameTags = _parent._tags[ns][_name]; auto targetIndex = sameNameTags.countUntil(this); _parent._tags[ns][_name].removeIndex(targetIndex); } // Remove from _parent._tags removeFromGroupedLookup(_namespace); removeFromGroupedLookup("*"); // Remove from _parent.allTags auto allTagsIndex = _parent.allTags.countUntil(this); _parent.allTags.removeIndex(allTagsIndex); // Remove from _parent.tagIndicies auto sameNamespaceTags = _parent.tagIndicies[_namespace]; auto tagIndiciesIndex = sameNamespaceTags.countUntil(allTagsIndex); _parent.tagIndicies[_namespace].removeIndex(tagIndiciesIndex); // Fixup other indicies foreach(ns, ref nsTagIndicies; _parent.tagIndicies) foreach(k, ref v; nsTagIndicies) if(v > allTagsIndex) v--; _parent.removeNamespaceIfEmpty(_namespace); _parent.updateId++; _parent = null; return this; } private void removeNamespaceIfEmpty(string namespace) { // If namespace has no attributes, remove it from attributeIndicies/_attributes if(namespace in attributeIndicies && attributeIndicies[namespace].length == 0) { attributeIndicies.remove(namespace); _attributes.remove(namespace); } // If namespace has no tags, remove it from tagIndicies/_tags if(namespace in tagIndicies && tagIndicies[namespace].length == 0) { tagIndicies.remove(namespace); _tags.remove(namespace); } // If namespace is now empty, remove it from allNamespaces if( namespace !in tagIndicies && namespace !in attributeIndicies ) { auto allNamespacesIndex = allNamespaces.length - allNamespaces.find(namespace).length; allNamespaces = allNamespaces[0..allNamespacesIndex] ~ allNamespaces[allNamespacesIndex+1..$]; } } struct NamedMemberRange(T, string membersGrouped) { private Tag tag; private string namespace; // "*" indicates "all namespaces" (ok since it's not a valid namespace name) private string name; private size_t updateId; // Tag's updateId when this range was created. this(Tag tag, string namespace, string name, size_t updateId) { this.tag = tag; this.namespace = namespace; this.name = name; this.updateId = updateId; frontIndex = 0; if( namespace in mixin("tag."~membersGrouped) && name in mixin("tag."~membersGrouped~"[namespace]") ) endIndex = mixin("tag."~membersGrouped~"[namespace][name].length"); else endIndex = 0; } invariant() { assert( this.updateId == tag.updateId, "This range has been invalidated by a change to the tag." ); } @property bool empty() { return frontIndex == endIndex; } private size_t frontIndex; @property T front() { return this[0]; } void popFront() { if(empty) throw new SDLangRangeException("Range is empty"); frontIndex++; } private size_t endIndex; // One past the last element @property T back() { return this[$-1]; } void popBack() { if(empty) throw new SDLangRangeException("Range is empty"); endIndex--; } alias length opDollar; @property size_t length() { return endIndex - frontIndex; } @property typeof(this) save() { auto r = typeof(this)(this.tag, this.namespace, this.name, this.updateId); r.frontIndex = this.frontIndex; r.endIndex = this.endIndex; return r; } typeof(this) opSlice() { return save(); } typeof(this) opSlice(size_t start, size_t end) { auto r = save(); r.frontIndex = this.frontIndex + start; r.endIndex = this.frontIndex + end; if( r.frontIndex > this.endIndex || r.endIndex > this.endIndex || r.frontIndex > r.endIndex ) throw new SDLangRangeException("Slice out of range"); return r; } T opIndex(size_t index) { if(empty) throw new SDLangRangeException("Range is empty"); return mixin("tag."~membersGrouped~"[namespace][name][frontIndex+index]"); } } struct MemberRange(T, string allMembers, string memberIndicies, string membersGrouped) { private Tag tag; private string namespace; // "*" indicates "all namespaces" (ok since it's not a valid namespace name) private bool isMaybe; private size_t updateId; // Tag's updateId when this range was created. private size_t initialEndIndex; this(Tag tag, string namespace, bool isMaybe) { this.tag = tag; this.namespace = namespace; this.updateId = tag.updateId; this.isMaybe = isMaybe; frontIndex = 0; if(namespace == "*") initialEndIndex = mixin("tag."~allMembers~".length"); else if(namespace in mixin("tag."~memberIndicies)) initialEndIndex = mixin("tag."~memberIndicies~"[namespace].length"); else initialEndIndex = 0; endIndex = initialEndIndex; } invariant() { assert( this.updateId == tag.updateId, "This range has been invalidated by a change to the tag." ); } @property bool empty() { return frontIndex == endIndex; } private size_t frontIndex; @property T front() { return this[0]; } void popFront() { if(empty) throw new SDLangRangeException("Range is empty"); frontIndex++; } private size_t endIndex; // One past the last element @property T back() { return this[$-1]; } void popBack() { if(empty) throw new SDLangRangeException("Range is empty"); endIndex--; } alias length opDollar; @property size_t length() { return endIndex - frontIndex; } @property typeof(this) save() { auto r = typeof(this)(this.tag, this.namespace, this.isMaybe); r.frontIndex = this.frontIndex; r.endIndex = this.endIndex; r.initialEndIndex = this.initialEndIndex; r.updateId = this.updateId; return r; } typeof(this) opSlice() { return save(); } typeof(this) opSlice(size_t start, size_t end) { auto r = save(); r.frontIndex = this.frontIndex + start; r.endIndex = this.frontIndex + end; if( r.frontIndex > this.endIndex || r.endIndex > this.endIndex || r.frontIndex > r.endIndex ) throw new SDLangRangeException("Slice out of range"); return r; } T opIndex(size_t index) { if(empty) throw new SDLangRangeException("Range is empty"); if(namespace == "*") return mixin("tag."~allMembers~"[ frontIndex+index ]"); else return mixin("tag."~allMembers~"[ tag."~memberIndicies~"[namespace][frontIndex+index] ]"); } alias NamedMemberRange!(T,membersGrouped) ThisNamedMemberRange; ThisNamedMemberRange opIndex(string name) { if(frontIndex != 0 || endIndex != initialEndIndex) { throw new SDLangRangeException( "Cannot lookup tags/attributes by name on a subset of a range, "~ "only across the entire tag. "~ "Please make sure you haven't called popFront or popBack on this "~ "range and that you aren't using a slice of the range." ); } if(!isMaybe && empty) throw new SDLangRangeException("Range is empty"); if(!isMaybe && name !in this) throw new SDLangRangeException(`No such `~T.stringof~` named: "`~name~`"`); return ThisNamedMemberRange(tag, namespace, name, updateId); } bool opBinaryRight(string op)(string name) if(op=="in") { if(frontIndex != 0 || endIndex != initialEndIndex) { throw new SDLangRangeException( "Cannot lookup tags/attributes by name on a subset of a range, "~ "only across the entire tag. "~ "Please make sure you haven't called popFront or popBack on this "~ "range and that you aren't using a slice of the range." ); } return namespace in mixin("tag."~membersGrouped) && name in mixin("tag."~membersGrouped~"[namespace]") && mixin("tag."~membersGrouped~"[namespace][name].length") > 0; } } struct NamespaceRange { private Tag tag; private bool isMaybe; private size_t updateId; // Tag's updateId when this range was created. this(Tag tag, bool isMaybe) { this.tag = tag; this.isMaybe = isMaybe; this.updateId = tag.updateId; frontIndex = 0; endIndex = tag.allNamespaces.length; } invariant() { assert( this.updateId == tag.updateId, "This range has been invalidated by a change to the tag." ); } @property bool empty() { return frontIndex == endIndex; } private size_t frontIndex; @property NamespaceAccess front() { return this[0]; } void popFront() { if(empty) throw new SDLangRangeException("Range is empty"); frontIndex++; } private size_t endIndex; // One past the last element @property NamespaceAccess back() { return this[$-1]; } void popBack() { if(empty) throw new SDLangRangeException("Range is empty"); endIndex--; } alias length opDollar; @property size_t length() { return endIndex - frontIndex; } @property NamespaceRange save() { auto r = NamespaceRange(this.tag, this.isMaybe); r.frontIndex = this.frontIndex; r.endIndex = this.endIndex; r.updateId = this.updateId; return r; } typeof(this) opSlice() { return save(); } typeof(this) opSlice(size_t start, size_t end) { auto r = save(); r.frontIndex = this.frontIndex + start; r.endIndex = this.frontIndex + end; if( r.frontIndex > this.endIndex || r.endIndex > this.endIndex || r.frontIndex > r.endIndex ) throw new SDLangRangeException("Slice out of range"); return r; } NamespaceAccess opIndex(size_t index) { if(empty) throw new SDLangRangeException("Range is empty"); auto namespace = tag.allNamespaces[frontIndex+index]; return NamespaceAccess( namespace, AttributeRange(tag, namespace, isMaybe), TagRange(tag, namespace, isMaybe) ); } NamespaceAccess opIndex(string namespace) { if(!isMaybe && empty) throw new SDLangRangeException("Range is empty"); if(!isMaybe && namespace !in this) throw new SDLangRangeException(`No such namespace: "`~namespace~`"`); return NamespaceAccess( namespace, AttributeRange(tag, namespace, isMaybe), TagRange(tag, namespace, isMaybe) ); } /// Inefficient when range is a slice or has used popFront/popBack, but it works. bool opBinaryRight(string op)(string namespace) if(op=="in") { if(frontIndex == 0 && endIndex == tag.allNamespaces.length) { return namespace in tag.attributeIndicies || namespace in tag.tagIndicies; } else // Slower fallback method return tag.allNamespaces[frontIndex..endIndex].canFind(namespace); } } struct NamespaceAccess { string name; AttributeRange attributes; TagRange tags; } alias MemberRange!(Attribute, "allAttributes", "attributeIndicies", "_attributes") AttributeRange; alias MemberRange!(Tag, "allTags", "tagIndicies", "_tags" ) TagRange; static assert(isRandomAccessRange!AttributeRange); static assert(isRandomAccessRange!TagRange); static assert(isRandomAccessRange!NamespaceRange); /// Access all attributes that don't have a namespace @property AttributeRange attributes() { return AttributeRange(this, "", false); } /// Access all direct-child tags that don't have a namespace @property TagRange tags() { return TagRange(this, "", false); } /// Access all namespaces in this tag, and the attributes/tags within them. @property NamespaceRange namespaces() { return NamespaceRange(this, false); } /// Access all attributes and tags regardless of namespace. @property NamespaceAccess all() { // "*" isn't a valid namespace name, so we can use it to indicate "all namespaces" return NamespaceAccess( "*", AttributeRange(this, "*", false), TagRange(this, "*", false) ); } struct MaybeAccess { Tag tag; /// Access all attributes that don't have a namespace @property AttributeRange attributes() { return AttributeRange(tag, "", true); } /// Access all direct-child tags that don't have a namespace @property TagRange tags() { return TagRange(tag, "", true); } /// Access all namespaces in this tag, and the attributes/tags within them. @property NamespaceRange namespaces() { return NamespaceRange(tag, true); } /// Access all attributes and tags regardless of namespace. @property NamespaceAccess all() { // "*" isn't a valid namespace name, so we can use it to indicate "all namespaces" return NamespaceAccess( "*", AttributeRange(tag, "*", true), TagRange(tag, "*", true) ); } } /// Access 'attributes', 'tags', 'namespaces' and 'all' like normal, /// except that looking up a non-existent name/namespace with /// opIndex(string) results in an empty array instead of a thrown SDLangRangeException. @property MaybeAccess maybe() { return MaybeAccess(this); } override bool opEquals(Object o) { auto t = cast(Tag)o; if(!t) return false; if(_namespace != t._namespace || _name != t._name) return false; if( values .length != t.values .length || allAttributes .length != t.allAttributes.length || allNamespaces .length != t.allNamespaces.length || allTags .length != t.allTags .length ) return false; if(values != t.values) return false; if(allNamespaces != t.allNamespaces) return false; if(allAttributes != t.allAttributes) return false; // Ok because cycles are not allowed //TODO: Actually check for or prevent cycles. return allTags == t.allTags; } /// Treats 'this' as the root tag. Note that root tags cannot have /// values or attributes, and cannot be part of a namespace. /// If this isn't a valid root tag, 'SDLangValidationException' will be thrown. string toSDLDocument()(string indent="\t", int indentLevel=0) { Appender!string sink; toSDLDocument(sink, indent, indentLevel); return sink.data; } ///ditto void toSDLDocument(Sink)(ref Sink sink, string indent="\t", int indentLevel=0) if(isOutputRange!(Sink,char)) { if(values.length > 0) throw new SDLangValidationException("Root tags cannot have any values, only child tags."); if(allAttributes.length > 0) throw new SDLangValidationException("Root tags cannot have any attributes, only child tags."); if(_namespace != "") throw new SDLangValidationException("Root tags cannot have a namespace."); foreach(tag; allTags) tag.toSDLString(sink, indent, indentLevel); } /// Output this entire tag in SDL format. Does *not* treat 'this' as /// a root tag. If you intend this to be the root of a standard SDL /// document, use 'toSDLDocument' instead. string toSDLString()(string indent="\t", int indentLevel=0) { Appender!string sink; toSDLString(sink, indent, indentLevel); return sink.data; } ///ditto void toSDLString(Sink)(ref Sink sink, string indent="\t", int indentLevel=0) if(isOutputRange!(Sink,char)) { if(_name == "" && values.length == 0) throw new SDLangValidationException("Anonymous tags must have at least one value."); if(_name == "" && _namespace != "") throw new SDLangValidationException("Anonymous tags cannot have a namespace."); // Indent foreach(i; 0..indentLevel) sink.put(indent); // Name if(_namespace != "") { sink.put(_namespace); sink.put(':'); } sink.put(_name); // Values foreach(i, v; values) { // Omit the first space for anonymous tags if(_name != "" || i > 0) sink.put(' '); v.toSDLString(sink); } // Attributes foreach(attr; allAttributes) { sink.put(' '); attr.toSDLString(sink); } // Child tags bool foundChild=false; foreach(tag; allTags) { if(!foundChild) { sink.put(" {\n"); foundChild = true; } tag.toSDLString(sink, indent, indentLevel+1); } if(foundChild) { foreach(i; 0..indentLevel) sink.put(indent); sink.put("}\n"); } else sink.put("\n"); } /// Not the most efficient, but it works. string toDebugString() { import std.algorithm : sort; Appender!string buf; buf.put("\n"); buf.put("Tag "); if(_namespace != "") { buf.put("["); buf.put(_namespace); buf.put("]"); } buf.put("'%s':\n".format(_name)); // Values foreach(val; values) buf.put(" (%s): %s\n".format(.toString(val.type), val)); // Attributes foreach(attrNamespace; _attributes.keys.sort()) if(attrNamespace != "*") foreach(attrName; _attributes[attrNamespace].keys.sort()) foreach(attr; _attributes[attrNamespace][attrName]) { string namespaceStr; if(attr._namespace != "") namespaceStr = "["~attr._namespace~"]"; buf.put( " %s%s(%s): %s\n".format( namespaceStr, attr._name, .toString(attr.value.type), attr.value ) ); } // Children foreach(tagNamespace; _tags.keys.sort()) if(tagNamespace != "*") foreach(tagName; _tags[tagNamespace].keys.sort()) foreach(tag; _tags[tagNamespace][tagName]) buf.put( tag.toDebugString().replace("\n", "\n ") ); return buf.data; } } version(sdlangUnittest) { private void testRandomAccessRange(R, E)(R range, E[] expected, bool function(E, E) equals=null) { static assert(isRandomAccessRange!R); static assert(is(ElementType!R == E)); static assert(hasLength!R); static assert(!isInfinite!R); assert(range.length == expected.length); if(range.length == 0) { assert(range.empty); return; } static bool defaultEquals(E e1, E e2) { return e1 == e2; } if(equals is null) equals = &defaultEquals; assert(equals(range.front, expected[0])); assert(equals(range.front, expected[0])); // Ensure consistent result from '.front' assert(equals(range.front, expected[0])); // Ensure consistent result from '.front' assert(equals(range.back, expected[$-1])); assert(equals(range.back, expected[$-1])); // Ensure consistent result from '.back' assert(equals(range.back, expected[$-1])); // Ensure consistent result from '.back' // Forward iteration auto original = range.save; auto r2 = range.save; foreach(i; 0..expected.length) { //trace("Forward iteration: ", i); // Test length/empty assert(range.length == expected.length - i); assert(range.length == r2.length); assert(!range.empty); assert(!r2.empty); // Test front assert(equals(range.front, expected[i])); assert(equals(range.front, r2.front)); // Test back assert(equals(range.back, expected[$-1])); assert(equals(range.back, r2.back)); // Test opIndex(0) assert(equals(range[0], expected[i])); assert(equals(range[0], r2[0])); // Test opIndex($-1) assert(equals(range[$-1], expected[$-1])); assert(equals(range[$-1], r2[$-1])); // Test popFront range.popFront(); assert(range.length == r2.length - 1); r2.popFront(); assert(range.length == r2.length); } assert(range.empty); assert(r2.empty); assert(original.length == expected.length); // Backwards iteration range = original.save; r2 = original.save; foreach(i; iota(0, expected.length).retro()) { //trace("Backwards iteration: ", i); // Test length/empty assert(range.length == i+1); assert(range.length == r2.length); assert(!range.empty); assert(!r2.empty); // Test front assert(equals(range.front, expected[0])); assert(equals(range.front, r2.front)); // Test back assert(equals(range.back, expected[i])); assert(equals(range.back, r2.back)); // Test opIndex(0) assert(equals(range[0], expected[0])); assert(equals(range[0], r2[0])); // Test opIndex($-1) assert(equals(range[$-1], expected[i])); assert(equals(range[$-1], r2[$-1])); // Test popBack range.popBack(); assert(range.length == r2.length - 1); r2.popBack(); assert(range.length == r2.length); } assert(range.empty); assert(r2.empty); assert(original.length == expected.length); // Random access range = original.save; r2 = original.save; foreach(i; 0..expected.length) { //trace("Random access: ", i); // Test length/empty assert(range.length == expected.length); assert(range.length == r2.length); assert(!range.empty); assert(!r2.empty); // Test front assert(equals(range.front, expected[0])); assert(equals(range.front, r2.front)); // Test back assert(equals(range.back, expected[$-1])); assert(equals(range.back, r2.back)); // Test opIndex(i) assert(equals(range[i], expected[i])); assert(equals(range[i], r2[i])); } assert(!range.empty); assert(!r2.empty); assert(original.length == expected.length); } } version(sdlangUnittest) unittest { import sdlang.parser; writeln("Unittesting sdlang ast..."); stdout.flush(); Tag root; root = parseSource(""); testRandomAccessRange(root.attributes, cast( Attribute[])[]); testRandomAccessRange(root.tags, cast( Tag[])[]); testRandomAccessRange(root.namespaces, cast(Tag.NamespaceAccess[])[]); root = parseSource(` blue 3 "Lee" isThree=true blue 5 "Chan" 12345 isThree=false stuff:orange 1 2 3 2 1 stuff:square points=4 dimensions=2 points="Still four" stuff:triangle data:points=3 data:dimensions=2 nothing namespaces small:A=1 med:A=2 big:A=3 small:B=10 big:B=30 people visitor:a=1 b=2 { chiyo "Small" "Flies?" nemesis="Car" score=100 yukari visitor:sana tomo visitor:hayama } `); auto blue3 = new Tag( null, "", "blue", [ Value(3), Value("Lee") ], [ new Attribute("isThree", Value(true)) ], null ); auto blue5 = new Tag( null, "", "blue", [ Value(5), Value("Chan"), Value(12345) ], [ new Attribute("isThree", Value(false)) ], null ); auto orange = new Tag( null, "stuff", "orange", [ Value(1), Value(2), Value(3), Value(2), Value(1) ], null, null ); auto square = new Tag( null, "stuff", "square", null, [ new Attribute("points", Value(4)), new Attribute("dimensions", Value(2)), new Attribute("points", Value("Still four")), ], null ); auto triangle = new Tag( null, "stuff", "triangle", null, [ new Attribute("data", "points", Value(3)), new Attribute("data", "dimensions", Value(2)), ], null ); auto nothing = new Tag( null, "", "nothing", null, null, null ); auto namespaces = new Tag( null, "", "namespaces", null, [ new Attribute("small", "A", Value(1)), new Attribute("med", "A", Value(2)), new Attribute("big", "A", Value(3)), new Attribute("small", "B", Value(10)), new Attribute("big", "B", Value(30)), ], null ); auto chiyo = new Tag( null, "", "chiyo", [ Value("Small"), Value("Flies?") ], [ new Attribute("nemesis", Value("Car")), new Attribute("score", Value(100)), ], null ); auto chiyo_ = new Tag( null, "", "chiyo_", [ Value("Small"), Value("Flies?") ], [ new Attribute("nemesis", Value("Car")), new Attribute("score", Value(100)), ], null ); auto yukari = new Tag( null, "", "yukari", null, null, null ); auto sana = new Tag( null, "visitor", "sana", null, null, null ); auto sana_ = new Tag( null, "visitor", "sana_", null, null, null ); auto sanaVisitor_ = new Tag( null, "visitor_", "sana_", null, null, null ); auto tomo = new Tag( null, "", "tomo", null, null, null ); auto hayama = new Tag( null, "visitor", "hayama", null, null, null ); auto people = new Tag( null, "", "people", null, [ new Attribute("visitor", "a", Value(1)), new Attribute("b", Value(2)), ], [chiyo, yukari, sana, tomo, hayama] ); assert(blue3 .opEquals( blue3 )); assert(blue5 .opEquals( blue5 )); assert(orange .opEquals( orange )); assert(square .opEquals( square )); assert(triangle .opEquals( triangle )); assert(nothing .opEquals( nothing )); assert(namespaces .opEquals( namespaces )); assert(people .opEquals( people )); assert(chiyo .opEquals( chiyo )); assert(yukari .opEquals( yukari )); assert(sana .opEquals( sana )); assert(tomo .opEquals( tomo )); assert(hayama .opEquals( hayama )); assert(!blue3.opEquals(orange)); assert(!blue3.opEquals(people)); assert(!blue3.opEquals(sana)); assert(!blue3.opEquals(blue5)); assert(!blue5.opEquals(blue3)); alias Tag.NamespaceAccess NSA; static bool namespaceEquals(NSA n1, NSA n2) { return n1.name == n2.name; } testRandomAccessRange(root.attributes, cast(Attribute[])[]); testRandomAccessRange(root.tags, [blue3, blue5, nothing, namespaces, people]); testRandomAccessRange(root.namespaces, [NSA(""), NSA("stuff")], &namespaceEquals); testRandomAccessRange(root.namespaces[0].tags, [blue3, blue5, nothing, namespaces, people]); testRandomAccessRange(root.namespaces[1].tags, [orange, square, triangle]); assert("" in root.namespaces); assert("stuff" in root.namespaces); assert("foobar" !in root.namespaces); testRandomAccessRange(root.namespaces[ ""].tags, [blue3, blue5, nothing, namespaces, people]); testRandomAccessRange(root.namespaces["stuff"].tags, [orange, square, triangle]); testRandomAccessRange(root.all.attributes, cast(Attribute[])[]); testRandomAccessRange(root.all.tags, [blue3, blue5, orange, square, triangle, nothing, namespaces, people]); testRandomAccessRange(root.all.tags[], [blue3, blue5, orange, square, triangle, nothing, namespaces, people]); testRandomAccessRange(root.all.tags[3..6], [square, triangle, nothing]); assert("blue" in root.tags); assert("nothing" in root.tags); assert("people" in root.tags); assert("orange" !in root.tags); assert("square" !in root.tags); assert("foobar" !in root.tags); assert("blue" in root.all.tags); assert("nothing" in root.all.tags); assert("people" in root.all.tags); assert("orange" in root.all.tags); assert("square" in root.all.tags); assert("foobar" !in root.all.tags); assert("orange" in root.namespaces["stuff"].tags); assert("square" in root.namespaces["stuff"].tags); assert("square" in root.namespaces["stuff"].tags); assert("foobar" !in root.attributes); assert("foobar" !in root.all.attributes); assert("foobar" !in root.namespaces["stuff"].attributes); assert("blue" !in root.attributes); assert("blue" !in root.all.attributes); assert("blue" !in root.namespaces["stuff"].attributes); testRandomAccessRange(root.tags["nothing"], [nothing]); testRandomAccessRange(root.tags["blue"], [blue3, blue5]); testRandomAccessRange(root.namespaces["stuff"].tags["orange"], [orange]); testRandomAccessRange(root.all.tags["nothing"], [nothing]); testRandomAccessRange(root.all.tags["blue"], [blue3, blue5]); testRandomAccessRange(root.all.tags["orange"], [orange]); assertThrown!SDLangRangeException(root.tags["foobar"]); assertThrown!SDLangRangeException(root.all.tags["foobar"]); assertThrown!SDLangRangeException(root.attributes["foobar"]); assertThrown!SDLangRangeException(root.all.attributes["foobar"]); // DMD Issue #12585 causes a segfault in these two tests when using 2.064 or 2.065, // so work around it. //assertThrown!SDLangRangeException(root.namespaces["foobar"].tags["foobar"]); //assertThrown!SDLangRangeException(root.namespaces["foobar"].attributes["foobar"]); bool didCatch = false; try auto x = root.namespaces["foobar"].tags["foobar"]; catch(SDLangRangeException e) didCatch = true; assert(didCatch); didCatch = false; try auto x = root.namespaces["foobar"].attributes["foobar"]; catch(SDLangRangeException e) didCatch = true; assert(didCatch); testRandomAccessRange(root.maybe.tags["nothing"], [nothing]); testRandomAccessRange(root.maybe.tags["blue"], [blue3, blue5]); testRandomAccessRange(root.maybe.namespaces["stuff"].tags["orange"], [orange]); testRandomAccessRange(root.maybe.all.tags["nothing"], [nothing]); testRandomAccessRange(root.maybe.all.tags["blue"], [blue3, blue5]); testRandomAccessRange(root.maybe.all.tags["blue"][], [blue3, blue5]); testRandomAccessRange(root.maybe.all.tags["blue"][0..1], [blue3]); testRandomAccessRange(root.maybe.all.tags["blue"][1..2], [blue5]); testRandomAccessRange(root.maybe.all.tags["orange"], [orange]); testRandomAccessRange(root.maybe.tags["foobar"], cast(Tag[])[]); testRandomAccessRange(root.maybe.all.tags["foobar"], cast(Tag[])[]); testRandomAccessRange(root.maybe.namespaces["foobar"].tags["foobar"], cast(Tag[])[]); testRandomAccessRange(root.maybe.attributes["foobar"], cast(Attribute[])[]); testRandomAccessRange(root.maybe.all.attributes["foobar"], cast(Attribute[])[]); testRandomAccessRange(root.maybe.namespaces["foobar"].attributes["foobar"], cast(Attribute[])[]); testRandomAccessRange(blue3.attributes, [ new Attribute("isThree", Value(true)) ]); testRandomAccessRange(blue3.tags, cast(Tag[])[]); testRandomAccessRange(blue3.namespaces, [NSA("")], &namespaceEquals); testRandomAccessRange(blue3.all.attributes, [ new Attribute("isThree", Value(true)) ]); testRandomAccessRange(blue3.all.tags, cast(Tag[])[]); testRandomAccessRange(blue5.attributes, [ new Attribute("isThree", Value(false)) ]); testRandomAccessRange(blue5.tags, cast(Tag[])[]); testRandomAccessRange(blue5.namespaces, [NSA("")], &namespaceEquals); testRandomAccessRange(blue5.all.attributes, [ new Attribute("isThree", Value(false)) ]); testRandomAccessRange(blue5.all.tags, cast(Tag[])[]); testRandomAccessRange(orange.attributes, cast(Attribute[])[]); testRandomAccessRange(orange.tags, cast(Tag[])[]); testRandomAccessRange(orange.namespaces, cast(NSA[])[], &namespaceEquals); testRandomAccessRange(orange.all.attributes, cast(Attribute[])[]); testRandomAccessRange(orange.all.tags, cast(Tag[])[]); testRandomAccessRange(square.attributes, [ new Attribute("points", Value(4)), new Attribute("dimensions", Value(2)), new Attribute("points", Value("Still four")), ]); testRandomAccessRange(square.tags, cast(Tag[])[]); testRandomAccessRange(square.namespaces, [NSA("")], &namespaceEquals); testRandomAccessRange(square.all.attributes, [ new Attribute("points", Value(4)), new Attribute("dimensions", Value(2)), new Attribute("points", Value("Still four")), ]); testRandomAccessRange(square.all.tags, cast(Tag[])[]); testRandomAccessRange(triangle.attributes, cast(Attribute[])[]); testRandomAccessRange(triangle.tags, cast(Tag[])[]); testRandomAccessRange(triangle.namespaces, [NSA("data")], &namespaceEquals); testRandomAccessRange(triangle.namespaces[0].attributes, [ new Attribute("data", "points", Value(3)), new Attribute("data", "dimensions", Value(2)), ]); assert("data" in triangle.namespaces); assert("foobar" !in triangle.namespaces); testRandomAccessRange(triangle.namespaces["data"].attributes, [ new Attribute("data", "points", Value(3)), new Attribute("data", "dimensions", Value(2)), ]); testRandomAccessRange(triangle.all.attributes, [ new Attribute("data", "points", Value(3)), new Attribute("data", "dimensions", Value(2)), ]); testRandomAccessRange(triangle.all.tags, cast(Tag[])[]); testRandomAccessRange(nothing.attributes, cast(Attribute[])[]); testRandomAccessRange(nothing.tags, cast(Tag[])[]); testRandomAccessRange(nothing.namespaces, cast(NSA[])[], &namespaceEquals); testRandomAccessRange(nothing.all.attributes, cast(Attribute[])[]); testRandomAccessRange(nothing.all.tags, cast(Tag[])[]); testRandomAccessRange(namespaces.attributes, cast(Attribute[])[]); testRandomAccessRange(namespaces.tags, cast(Tag[])[]); testRandomAccessRange(namespaces.namespaces, [NSA("small"), NSA("med"), NSA("big")], &namespaceEquals); testRandomAccessRange(namespaces.namespaces[], [NSA("small"), NSA("med"), NSA("big")], &namespaceEquals); testRandomAccessRange(namespaces.namespaces[1..2], [NSA("med")], &namespaceEquals); testRandomAccessRange(namespaces.namespaces[0].attributes, [ new Attribute("small", "A", Value(1)), new Attribute("small", "B", Value(10)), ]); testRandomAccessRange(namespaces.namespaces[1].attributes, [ new Attribute("med", "A", Value(2)), ]); testRandomAccessRange(namespaces.namespaces[2].attributes, [ new Attribute("big", "A", Value(3)), new Attribute("big", "B", Value(30)), ]); testRandomAccessRange(namespaces.namespaces[1..2][0].attributes, [ new Attribute("med", "A", Value(2)), ]); assert("small" in namespaces.namespaces); assert("med" in namespaces.namespaces); assert("big" in namespaces.namespaces); assert("foobar" !in namespaces.namespaces); assert("small" !in namespaces.namespaces[1..2]); assert("med" in namespaces.namespaces[1..2]); assert("big" !in namespaces.namespaces[1..2]); assert("foobar" !in namespaces.namespaces[1..2]); testRandomAccessRange(namespaces.namespaces["small"].attributes, [ new Attribute("small", "A", Value(1)), new Attribute("small", "B", Value(10)), ]); testRandomAccessRange(namespaces.namespaces["med"].attributes, [ new Attribute("med", "A", Value(2)), ]); testRandomAccessRange(namespaces.namespaces["big"].attributes, [ new Attribute("big", "A", Value(3)), new Attribute("big", "B", Value(30)), ]); testRandomAccessRange(namespaces.all.attributes, [ new Attribute("small", "A", Value(1)), new Attribute("med", "A", Value(2)), new Attribute("big", "A", Value(3)), new Attribute("small", "B", Value(10)), new Attribute("big", "B", Value(30)), ]); testRandomAccessRange(namespaces.all.attributes[], [ new Attribute("small", "A", Value(1)), new Attribute("med", "A", Value(2)), new Attribute("big", "A", Value(3)), new Attribute("small", "B", Value(10)), new Attribute("big", "B", Value(30)), ]); testRandomAccessRange(namespaces.all.attributes[2..4], [ new Attribute("big", "A", Value(3)), new Attribute("small", "B", Value(10)), ]); testRandomAccessRange(namespaces.all.tags, cast(Tag[])[]); assert("A" !in namespaces.attributes); assert("B" !in namespaces.attributes); assert("foobar" !in namespaces.attributes); assert("A" in namespaces.all.attributes); assert("B" in namespaces.all.attributes); assert("foobar" !in namespaces.all.attributes); assert("A" in namespaces.namespaces["small"].attributes); assert("B" in namespaces.namespaces["small"].attributes); assert("foobar" !in namespaces.namespaces["small"].attributes); assert("A" in namespaces.namespaces["med"].attributes); assert("B" !in namespaces.namespaces["med"].attributes); assert("foobar" !in namespaces.namespaces["med"].attributes); assert("A" in namespaces.namespaces["big"].attributes); assert("B" in namespaces.namespaces["big"].attributes); assert("foobar" !in namespaces.namespaces["big"].attributes); assert("foobar" !in namespaces.tags); assert("foobar" !in namespaces.all.tags); assert("foobar" !in namespaces.namespaces["small"].tags); assert("A" !in namespaces.tags); assert("A" !in namespaces.all.tags); assert("A" !in namespaces.namespaces["small"].tags); testRandomAccessRange(namespaces.namespaces["small"].attributes["A"], [ new Attribute("small", "A", Value(1)), ]); testRandomAccessRange(namespaces.namespaces["med"].attributes["A"], [ new Attribute("med", "A", Value(2)), ]); testRandomAccessRange(namespaces.namespaces["big"].attributes["A"], [ new Attribute("big", "A", Value(3)), ]); testRandomAccessRange(namespaces.all.attributes["A"], [ new Attribute("small", "A", Value(1)), new Attribute("med", "A", Value(2)), new Attribute("big", "A", Value(3)), ]); testRandomAccessRange(namespaces.all.attributes["B"], [ new Attribute("small", "B", Value(10)), new Attribute("big", "B", Value(30)), ]); testRandomAccessRange(chiyo.attributes, [ new Attribute("nemesis", Value("Car")), new Attribute("score", Value(100)), ]); testRandomAccessRange(chiyo.tags, cast(Tag[])[]); testRandomAccessRange(chiyo.namespaces, [NSA("")], &namespaceEquals); testRandomAccessRange(chiyo.all.attributes, [ new Attribute("nemesis", Value("Car")), new Attribute("score", Value(100)), ]); testRandomAccessRange(chiyo.all.tags, cast(Tag[])[]); testRandomAccessRange(yukari.attributes, cast(Attribute[])[]); testRandomAccessRange(yukari.tags, cast(Tag[])[]); testRandomAccessRange(yukari.namespaces, cast(NSA[])[], &namespaceEquals); testRandomAccessRange(yukari.all.attributes, cast(Attribute[])[]); testRandomAccessRange(yukari.all.tags, cast(Tag[])[]); testRandomAccessRange(sana.attributes, cast(Attribute[])[]); testRandomAccessRange(sana.tags, cast(Tag[])[]); testRandomAccessRange(sana.namespaces, cast(NSA[])[], &namespaceEquals); testRandomAccessRange(sana.all.attributes, cast(Attribute[])[]); testRandomAccessRange(sana.all.tags, cast(Tag[])[]); testRandomAccessRange(people.attributes, [new Attribute("b", Value(2))]); testRandomAccessRange(people.tags, [chiyo, yukari, tomo]); testRandomAccessRange(people.namespaces, [NSA("visitor"), NSA("")], &namespaceEquals); testRandomAccessRange(people.namespaces[0].attributes, [new Attribute("visitor", "a", Value(1))]); testRandomAccessRange(people.namespaces[1].attributes, [new Attribute("b", Value(2))]); testRandomAccessRange(people.namespaces[0].tags, [sana, hayama]); testRandomAccessRange(people.namespaces[1].tags, [chiyo, yukari, tomo]); assert("visitor" in people.namespaces); assert("" in people.namespaces); assert("foobar" !in people.namespaces); testRandomAccessRange(people.namespaces["visitor"].attributes, [new Attribute("visitor", "a", Value(1))]); testRandomAccessRange(people.namespaces[ ""].attributes, [new Attribute("b", Value(2))]); testRandomAccessRange(people.namespaces["visitor"].tags, [sana, hayama]); testRandomAccessRange(people.namespaces[ ""].tags, [chiyo, yukari, tomo]); testRandomAccessRange(people.all.attributes, [ new Attribute("visitor", "a", Value(1)), new Attribute("b", Value(2)), ]); testRandomAccessRange(people.all.tags, [chiyo, yukari, sana, tomo, hayama]); people.attributes["b"][0].name = "b_"; people.namespaces["visitor"].attributes["a"][0].name = "a_"; people.tags["chiyo"][0].name = "chiyo_"; people.namespaces["visitor"].tags["sana"][0].name = "sana_"; assert("b_" in people.attributes); assert("a_" in people.namespaces["visitor"].attributes); assert("chiyo_" in people.tags); assert("sana_" in people.namespaces["visitor"].tags); assert(people.attributes["b_"][0] == new Attribute("b_", Value(2))); assert(people.namespaces["visitor"].attributes["a_"][0] == new Attribute("visitor", "a_", Value(1))); assert(people.tags["chiyo_"][0] == chiyo_); assert(people.namespaces["visitor"].tags["sana_"][0] == sana_); assert("b" !in people.attributes); assert("a" !in people.namespaces["visitor"].attributes); assert("chiyo" !in people.tags); assert("sana" !in people.namespaces["visitor"].tags); assert(people.maybe.attributes["b"].length == 0); assert(people.maybe.namespaces["visitor"].attributes["a"].length == 0); assert(people.maybe.tags["chiyo"].length == 0); assert(people.maybe.namespaces["visitor"].tags["sana"].length == 0); people.tags["tomo"][0].remove(); people.namespaces["visitor"].tags["hayama"][0].remove(); people.tags["chiyo_"][0].remove(); testRandomAccessRange(people.tags, [yukari]); testRandomAccessRange(people.namespaces, [NSA("visitor"), NSA("")], &namespaceEquals); testRandomAccessRange(people.namespaces[0].tags, [sana_]); testRandomAccessRange(people.namespaces[1].tags, [yukari]); assert("visitor" in people.namespaces); assert("" in people.namespaces); assert("foobar" !in people.namespaces); testRandomAccessRange(people.namespaces["visitor"].tags, [sana_]); testRandomAccessRange(people.namespaces[ ""].tags, [yukari]); testRandomAccessRange(people.all.tags, [yukari, sana_]); people.attributes["b_"][0].namespace = "_"; people.namespaces["visitor"].attributes["a_"][0].namespace = "visitor_"; assert("_" in people.namespaces); assert("visitor_" in people.namespaces); assert("" in people.namespaces); assert("visitor" in people.namespaces); people.namespaces["visitor"].tags["sana_"][0].namespace = "visitor_"; assert("_" in people.namespaces); assert("visitor_" in people.namespaces); assert("" in people.namespaces); assert("visitor" !in people.namespaces); assert(people.namespaces["_" ].attributes["b_"][0] == new Attribute("_", "b_", Value(2))); assert(people.namespaces["visitor_"].attributes["a_"][0] == new Attribute("visitor_", "a_", Value(1))); assert(people.namespaces["visitor_"].tags["sana_"][0] == sanaVisitor_); people.tags["yukari"][0].remove(); people.namespaces["visitor_"].tags["sana_"][0].remove(); people.namespaces["visitor_"].attributes["a_"][0].namespace = "visitor"; people.namespaces["_"].attributes["b_"][0].namespace = ""; testRandomAccessRange(people.tags, cast(Tag[])[]); testRandomAccessRange(people.namespaces, [NSA("visitor"), NSA("")], &namespaceEquals); testRandomAccessRange(people.namespaces[0].tags, cast(Tag[])[]); testRandomAccessRange(people.namespaces[1].tags, cast(Tag[])[]); assert("visitor" in people.namespaces); assert("" in people.namespaces); assert("foobar" !in people.namespaces); testRandomAccessRange(people.namespaces["visitor"].tags, cast(Tag[])[]); testRandomAccessRange(people.namespaces[ ""].tags, cast(Tag[])[]); testRandomAccessRange(people.all.tags, cast(Tag[])[]); people.namespaces["visitor"].attributes["a_"][0].remove(); testRandomAccessRange(people.attributes, [new Attribute("b_", Value(2))]); testRandomAccessRange(people.namespaces, [NSA("")], &namespaceEquals); testRandomAccessRange(people.namespaces[0].attributes, [new Attribute("b_", Value(2))]); assert("visitor" !in people.namespaces); assert("" in people.namespaces); assert("foobar" !in people.namespaces); testRandomAccessRange(people.namespaces[""].attributes, [new Attribute("b_", Value(2))]); testRandomAccessRange(people.all.attributes, [ new Attribute("b_", Value(2)), ]); people.attributes["b_"][0].remove(); testRandomAccessRange(people.attributes, cast(Attribute[])[]); testRandomAccessRange(people.namespaces, cast(NSA[])[], &namespaceEquals); assert("visitor" !in people.namespaces); assert("" !in people.namespaces); assert("foobar" !in people.namespaces); testRandomAccessRange(people.all.attributes, cast(Attribute[])[]); } // Regression test, issue #11: https://github.com/Abscissa/SDLang-D/issues/11 version(sdlangUnittest) unittest { import sdlang.parser; writeln("ast: Regression test issue #11..."); stdout.flush(); auto root = parseSource( `// a`); assert("a" in root.tags); root = parseSource( `// parent { child } `); auto child = new Tag( null, "", "child", null, null, null ); assert("parent" in root.tags); assert("child" !in root.tags); testRandomAccessRange(root.tags["parent"][0].tags, [child]); assert("child" in root.tags["parent"][0].tags); } dub-1.19.0/source/dub/internal/sdlang/exception.d000066400000000000000000000013641360435400500216610ustar00rootroot00000000000000// SDLang-D // Written in the D programming language. module dub.internal.sdlang.exception; version (Have_sdlang_d) public import sdlang.exception; else: import std.exception; import std.string; import dub.internal.sdlang.util; abstract class SDLangException : Exception { this(string msg) { super(msg); } } class SDLangParseException : SDLangException { Location location; bool hasLocation; this(string msg) { hasLocation = false; super(msg); } this(Location location, string msg) { hasLocation = true; super("%s: %s".format(location.toString(), msg)); } } class SDLangValidationException : SDLangException { this(string msg) { super(msg); } } class SDLangRangeException : SDLangException { this(string msg) { super(msg); } } dub-1.19.0/source/dub/internal/sdlang/lexer.d000066400000000000000000001727011360435400500210060ustar00rootroot00000000000000// SDLang-D // Written in the D programming language. module dub.internal.sdlang.lexer; version (Have_sdlang_d) public import sdlang.lexer; else: import std.algorithm; import std.array; import std.base64; import std.bigint; import std.conv; import std.datetime; import std.file; import std.traits; import std.typecons; import std.uni; import std.utf; import std.variant; import dub.internal.sdlang.exception; import dub.internal.sdlang.symbol; import dub.internal.sdlang.token; import dub.internal.sdlang.util; alias dub.internal.sdlang.util.startsWith startsWith; Token[] lexFile(string filename) { auto source = cast(string)read(filename); return lexSource(source, filename); } Token[] lexSource(string source, string filename=null) { auto lexer = scoped!Lexer(source, filename); // Can't use 'std.array.array(Range)' because 'lexer' is scoped // and therefore cannot have its reference copied. Appender!(Token[]) tokens; foreach(tok; lexer) tokens.put(tok); return tokens.data; } // Kind of a poor-man's yield, but fast. // Only to be used inside Lexer.popFront (and Lexer.this). private template accept(string symbolName) { static assert(symbolName != "Value", "Value symbols must also take a value."); enum accept = acceptImpl!(symbolName, "null"); } private template accept(string symbolName, string value) { static assert(symbolName == "Value", "Only a Value symbol can take a value."); enum accept = acceptImpl!(symbolName, value); } private template accept(string symbolName, string value, string startLocation, string endLocation) { static assert(symbolName == "Value", "Only a Value symbol can take a value."); enum accept = (" { _front = makeToken!"~symbolName.stringof~"; _front.value = "~value~"; _front.location = "~(startLocation==""? "tokenStart" : startLocation)~"; _front.data = source[ "~(startLocation==""? "tokenStart.index" : startLocation)~" .. "~(endLocation==""? "location.index" : endLocation)~" ]; return; } ").replace("\n", ""); } private template acceptImpl(string symbolName, string value) { enum acceptImpl = (" { _front = makeToken!"~symbolName.stringof~"; _front.value = "~value~"; return; } ").replace("\n", ""); } class Lexer { string source; string filename; Location location; /// Location of current character in source private dchar ch; // Current character private dchar nextCh; // Lookahead character private size_t nextPos; // Position of lookahead character (an index into source) private bool hasNextCh; // If false, then there's no more lookahead, just EOF private size_t posAfterLookahead; // Position after lookahead character (an index into source) private Location tokenStart; // The starting location of the token being lexed // Length so far of the token being lexed, not including current char private size_t tokenLength; // Length in UTF-8 code units private size_t tokenLength32; // Length in UTF-32 code units // Slight kludge: // If a numeric fragment is found after a Date (separated by arbitrary // whitespace), it could be the "hours" part of a DateTime, or it could // be a separate numeric literal that simply follows a plain Date. If the // latter, then the Date must be emitted, but numeric fragment that was // found after it needs to be saved for the the lexer's next iteration. // // It's a slight kludge, and could instead be implemented as a slightly // kludgey parser hack, but it's the only situation where SDL's lexing // needs to lookahead more than one character, so this is good enough. private struct LookaheadTokenInfo { bool exists = false; string numericFragment = ""; bool isNegative = false; Location tokenStart; } private LookaheadTokenInfo lookaheadTokenInfo; this(string source=null, string filename=null) { this.filename = filename; this.source = source; _front = Token(symbol!"Error", Location()); lookaheadTokenInfo = LookaheadTokenInfo.init; if( source.startsWith( ByteOrderMarks[BOM.UTF8] ) ) { source = source[ ByteOrderMarks[BOM.UTF8].length .. $ ]; this.source = source; } foreach(bom; ByteOrderMarks) if( source.startsWith(bom) ) error(Location(filename,0,0,0), "SDL spec only supports UTF-8, not UTF-16 or UTF-32"); if(source == "") mixin(accept!"EOF"); // Prime everything hasNextCh = true; nextCh = source.decode(posAfterLookahead); advanceChar(ErrorOnEOF.Yes); location = Location(filename, 0, 0, 0); popFront(); } @property bool empty() { return _front.symbol == symbol!"EOF"; } Token _front; @property Token front() { return _front; } @property bool isEOF() { return location.index == source.length && !lookaheadTokenInfo.exists; } private void error(string msg) { error(location, msg); } private void error(Location loc, string msg) { throw new SDLangParseException(loc, "Error: "~msg); } private Token makeToken(string symbolName)() { auto tok = Token(symbol!symbolName, tokenStart); tok.data = tokenData; return tok; } private @property string tokenData() { return source[ tokenStart.index .. location.index ]; } /// Check the lookahead character private bool lookahead(dchar ch) { return hasNextCh && nextCh == ch; } private bool lookahead(bool function(dchar) condition) { return hasNextCh && condition(nextCh); } private static bool isNewline(dchar ch) { return ch == '\n' || ch == '\r' || ch == lineSep || ch == paraSep; } /// Returns the length of the newline sequence, or zero if the current /// character is not a newline /// /// Note that there are only single character sequences and the two /// character sequence `\r\n` as used on Windows. private size_t isAtNewline() { if(ch == '\n' || ch == lineSep || ch == paraSep) return 1; else if(ch == '\r') return lookahead('\n') ? 2 : 1; else return 0; } /// Is 'ch' a valid base 64 character? private bool isBase64(dchar ch) { if(ch >= 'A' && ch <= 'Z') return true; if(ch >= 'a' && ch <= 'z') return true; if(ch >= '0' && ch <= '9') return true; return ch == '+' || ch == '/' || ch == '='; } /// Is the current character one that's allowed /// immediately *after* an int/float literal? private bool isEndOfNumber() { if(isEOF) return true; return !isDigit(ch) && ch != ':' && ch != '_' && !isAlpha(ch); } /// Is current character the last one in an ident? private bool isEndOfIdentCached = false; private bool _isEndOfIdent; private bool isEndOfIdent() { if(!isEndOfIdentCached) { if(!hasNextCh) _isEndOfIdent = true; else _isEndOfIdent = !isIdentChar(nextCh); isEndOfIdentCached = true; } return _isEndOfIdent; } /// Is 'ch' a character that's allowed *somewhere* in an identifier? private bool isIdentChar(dchar ch) { if(isAlpha(ch)) return true; else if(isNumber(ch)) return true; else return ch == '-' || ch == '_' || ch == '.' || ch == '$'; } private bool isDigit(dchar ch) { return ch >= '0' && ch <= '9'; } private enum KeywordResult { Accept, // Keyword is matched Continue, // Keyword is not matched *yet* Failed, // Keyword doesn't match } private KeywordResult checkKeyword(dstring keyword32) { // Still within length of keyword if(tokenLength32 < keyword32.length) { if(ch == keyword32[tokenLength32]) return KeywordResult.Continue; else return KeywordResult.Failed; } // At position after keyword else if(tokenLength32 == keyword32.length) { if(isEOF || !isIdentChar(ch)) { debug assert(tokenData == to!string(keyword32)); return KeywordResult.Accept; } else return KeywordResult.Failed; } assert(0, "Fell off end of keyword to check"); } enum ErrorOnEOF { No, Yes } /// Advance one code point. private void advanceChar(ErrorOnEOF errorOnEOF) { if(auto cnt = isAtNewline()) { if (cnt == 1) location.line++; location.col = 0; } else location.col++; location.index = nextPos; nextPos = posAfterLookahead; ch = nextCh; if(!hasNextCh) { if(errorOnEOF == ErrorOnEOF.Yes) error("Unexpected end of file"); return; } tokenLength32++; tokenLength = location.index - tokenStart.index; if(nextPos == source.length) { nextCh = dchar.init; hasNextCh = false; return; } nextCh = source.decode(posAfterLookahead); isEndOfIdentCached = false; } /// Advances the specified amount of characters private void advanceChar(size_t count, ErrorOnEOF errorOnEOF) { while(count-- > 0) advanceChar(errorOnEOF); } void popFront() { // -- Main Lexer ------------- eatWhite(); if(isEOF) mixin(accept!"EOF"); tokenStart = location; tokenLength = 0; tokenLength32 = 0; isEndOfIdentCached = false; if(lookaheadTokenInfo.exists) { tokenStart = lookaheadTokenInfo.tokenStart; auto prevLATokenInfo = lookaheadTokenInfo; lookaheadTokenInfo = LookaheadTokenInfo.init; lexNumeric(prevLATokenInfo); return; } if(ch == '=') { advanceChar(ErrorOnEOF.No); mixin(accept!"="); } else if(ch == '{') { advanceChar(ErrorOnEOF.No); mixin(accept!"{"); } else if(ch == '}') { advanceChar(ErrorOnEOF.No); mixin(accept!"}"); } else if(ch == ':') { advanceChar(ErrorOnEOF.No); mixin(accept!":"); } else if(ch == ';') { advanceChar(ErrorOnEOF.No); mixin(accept!"EOL"); } else if(auto cnt = isAtNewline()) { advanceChar(cnt, ErrorOnEOF.No); mixin(accept!"EOL"); } else if(isAlpha(ch) || ch == '_') lexIdentKeyword(); else if(ch == '"') lexRegularString(); else if(ch == '`') lexRawString(); else if(ch == '\'') lexCharacter(); else if(ch == '[') lexBinary(); else if(ch == '-' || ch == '.' || isDigit(ch)) lexNumeric(); else { advanceChar(ErrorOnEOF.No); error("Syntax error"); } } /// Lex Ident or Keyword private void lexIdentKeyword() { assert(isAlpha(ch) || ch == '_'); // Keyword struct Key { dstring name; Value value; bool failed = false; } static Key[5] keywords; static keywordsInited = false; if(!keywordsInited) { // Value (as a std.variant-based type) can't be statically inited keywords[0] = Key("true", Value(true )); keywords[1] = Key("false", Value(false)); keywords[2] = Key("on", Value(true )); keywords[3] = Key("off", Value(false)); keywords[4] = Key("null", Value(null )); keywordsInited = true; } foreach(ref key; keywords) key.failed = false; auto numKeys = keywords.length; do { foreach(ref key; keywords) if(!key.failed) { final switch(checkKeyword(key.name)) { case KeywordResult.Accept: mixin(accept!("Value", "key.value")); case KeywordResult.Continue: break; case KeywordResult.Failed: key.failed = true; numKeys--; break; } } if(numKeys == 0) { lexIdent(); return; } advanceChar(ErrorOnEOF.No); } while(!isEOF); foreach(ref key; keywords) if(!key.failed) if(key.name.length == tokenLength32+1) mixin(accept!("Value", "key.value")); mixin(accept!"Ident"); } /// Lex Ident private void lexIdent() { if(tokenLength == 0) assert(isAlpha(ch) || ch == '_'); while(!isEOF && isIdentChar(ch)) advanceChar(ErrorOnEOF.No); mixin(accept!"Ident"); } /// Lex regular string private void lexRegularString() { assert(ch == '"'); Appender!string buf; size_t spanStart = nextPos; // Doesn't include current character void updateBuf() { if(location.index == spanStart) return; buf.put( source[spanStart..location.index] ); } advanceChar(ErrorOnEOF.Yes); while(ch != '"') { if(ch == '\\') { updateBuf(); bool wasEscSequence = true; if(hasNextCh) { switch(nextCh) { case 'n': buf.put('\n'); break; case 'r': buf.put('\r'); break; case 't': buf.put('\t'); break; case '"': buf.put('\"'); break; case '\\': buf.put('\\'); break; default: wasEscSequence = false; break; } } if(wasEscSequence) { advanceChar(ErrorOnEOF.Yes); spanStart = nextPos; } else { eatWhite(false); spanStart = location.index; } } else if(isNewline(ch)) error("Unescaped newlines are only allowed in raw strings, not regular strings."); advanceChar(ErrorOnEOF.Yes); } updateBuf(); advanceChar(ErrorOnEOF.No); // Skip closing double-quote mixin(accept!("Value", "buf.data")); } /// Lex raw string private void lexRawString() { assert(ch == '`'); do advanceChar(ErrorOnEOF.Yes); while(ch != '`'); advanceChar(ErrorOnEOF.No); // Skip closing back-tick mixin(accept!("Value", "tokenData[1..$-1]")); } /// Lex character literal private void lexCharacter() { assert(ch == '\''); advanceChar(ErrorOnEOF.Yes); // Skip opening single-quote dchar value; if(ch == '\\') { advanceChar(ErrorOnEOF.Yes); // Skip escape backslash switch(ch) { case 'n': value = '\n'; break; case 'r': value = '\r'; break; case 't': value = '\t'; break; case '\'': value = '\''; break; case '\\': value = '\\'; break; default: error("Invalid escape sequence."); } } else if(isNewline(ch)) error("Newline not alowed in character literal."); else value = ch; advanceChar(ErrorOnEOF.Yes); // Skip the character itself if(ch == '\'') advanceChar(ErrorOnEOF.No); // Skip closing single-quote else error("Expected closing single-quote."); mixin(accept!("Value", "value")); } /// Lex base64 binary literal private void lexBinary() { assert(ch == '['); advanceChar(ErrorOnEOF.Yes); void eatBase64Whitespace() { while(!isEOF && isWhite(ch)) { if(isNewline(ch)) advanceChar(ErrorOnEOF.Yes); if(!isEOF && isWhite(ch)) eatWhite(); } } eatBase64Whitespace(); // Iterates all valid base64 characters, ending at ']'. // Skips all whitespace. Throws on invalid chars. struct Base64InputRange { Lexer lexer; private bool isInited = false; private int numInputCharsMod4 = 0; @property bool empty() { if(lexer.ch == ']') { if(numInputCharsMod4 != 0) lexer.error("Length of Base64 encoding must be a multiple of 4. ("~to!string(numInputCharsMod4)~")"); return true; } return false; } @property dchar front() { return lexer.ch; } void popFront() { auto lex = lexer; if(!isInited) { if(lexer.isBase64(lexer.ch)) { numInputCharsMod4++; numInputCharsMod4 %= 4; } isInited = true; } lex.advanceChar(lex.ErrorOnEOF.Yes); eatBase64Whitespace(); if(lex.isEOF) lex.error("Unexpected end of file."); if(lex.ch != ']') { if(!lex.isBase64(lex.ch)) lex.error("Invalid character in base64 binary literal."); numInputCharsMod4++; numInputCharsMod4 %= 4; } } } // This is a slow ugly hack. It's necessary because Base64.decode // currently requires the source to have known length. //TODO: Remove this when DMD issue #9543 is fixed. dchar[] tmpBuf = array(Base64InputRange(this)); Appender!(ubyte[]) outputBuf; // Ugly workaround for DMD issue #9102 //TODO: Remove this when DMD #9102 is fixed struct OutputBuf { void put(ubyte ch) { outputBuf.put(ch); } } try //Base64.decode(Base64InputRange(this), OutputBuf()); Base64.decode(tmpBuf, OutputBuf()); //TODO: Starting with dmd 2.062, this should be a Base64Exception catch(Exception e) error("Invalid character in base64 binary literal."); advanceChar(ErrorOnEOF.No); // Skip ']' mixin(accept!("Value", "outputBuf.data")); } private BigInt toBigInt(bool isNegative, string absValue) { auto num = BigInt(absValue); assert(num >= 0); if(isNegative) num = -num; return num; } /// Lex [0-9]+, but without emitting a token. /// This is used by the other numeric parsing functions. private string lexNumericFragment() { if(!isDigit(ch)) error("Expected a digit 0-9."); auto spanStart = location.index; do { advanceChar(ErrorOnEOF.No); } while(!isEOF && isDigit(ch)); return source[spanStart..location.index]; } /// Lex anything that starts with 0-9 or '-'. Ints, floats, dates, etc. private void lexNumeric(LookaheadTokenInfo laTokenInfo = LookaheadTokenInfo.init) { bool isNegative; string firstFragment; if(laTokenInfo.exists) { firstFragment = laTokenInfo.numericFragment; isNegative = laTokenInfo.isNegative; } else { assert(ch == '-' || ch == '.' || isDigit(ch)); // Check for negative isNegative = ch == '-'; if(isNegative) advanceChar(ErrorOnEOF.Yes); // Some floating point with omitted leading zero? if(ch == '.') { lexFloatingPoint(""); return; } firstFragment = lexNumericFragment(); } // Long integer (64-bit signed)? if(ch == 'L' || ch == 'l') { advanceChar(ErrorOnEOF.No); // BigInt(long.min) is a workaround for DMD issue #9548 auto num = toBigInt(isNegative, firstFragment); if(num < BigInt(long.min) || num > long.max) error(tokenStart, "Value doesn't fit in 64-bit signed long integer: "~to!string(num)); mixin(accept!("Value", "num.toLong()")); } // Float (32-bit signed)? else if(ch == 'F' || ch == 'f') { auto value = to!float(tokenData); advanceChar(ErrorOnEOF.No); mixin(accept!("Value", "value")); } // Double float (64-bit signed) with suffix? else if((ch == 'D' || ch == 'd') && !lookahead(':') ) { auto value = to!double(tokenData); advanceChar(ErrorOnEOF.No); mixin(accept!("Value", "value")); } // Decimal (128+ bits signed)? else if( (ch == 'B' || ch == 'b') && (lookahead('D') || lookahead('d')) ) { auto value = to!real(tokenData); advanceChar(ErrorOnEOF.No); advanceChar(ErrorOnEOF.No); mixin(accept!("Value", "value")); } // Some floating point? else if(ch == '.') lexFloatingPoint(firstFragment); // Some date? else if(ch == '/' && hasNextCh && isDigit(nextCh)) lexDate(isNegative, firstFragment); // Some time span? else if(ch == ':' || ch == 'd') lexTimeSpan(isNegative, firstFragment); // Integer (32-bit signed)? else if(isEndOfNumber()) { auto num = toBigInt(isNegative, firstFragment); if(num < int.min || num > int.max) error(tokenStart, "Value doesn't fit in 32-bit signed integer: "~to!string(num)); mixin(accept!("Value", "num.toInt()")); } // Invalid suffix else error("Invalid integer suffix."); } /// Lex any floating-point literal (after the initial numeric fragment was lexed) private void lexFloatingPoint(string firstPart) { assert(ch == '.'); advanceChar(ErrorOnEOF.No); auto secondPart = lexNumericFragment(); try { // Double float (64-bit signed) with suffix? if(ch == 'D' || ch == 'd') { auto value = to!double(tokenData); advanceChar(ErrorOnEOF.No); mixin(accept!("Value", "value")); } // Float (32-bit signed)? else if(ch == 'F' || ch == 'f') { auto value = to!float(tokenData); advanceChar(ErrorOnEOF.No); mixin(accept!("Value", "value")); } // Decimal (128+ bits signed)? else if(ch == 'B' || ch == 'b') { auto value = to!real(tokenData); advanceChar(ErrorOnEOF.Yes); if(!isEOF && (ch == 'D' || ch == 'd')) { advanceChar(ErrorOnEOF.No); if(isEndOfNumber()) mixin(accept!("Value", "value")); } error("Invalid floating point suffix."); } // Double float (64-bit signed) without suffix? else if(isEOF || !isIdentChar(ch)) { auto value = to!double(tokenData); mixin(accept!("Value", "value")); } // Invalid suffix else error("Invalid floating point suffix."); } catch(ConvException e) error("Invalid floating point literal."); } private Date makeDate(bool isNegative, string yearStr, string monthStr, string dayStr) { BigInt biTmp; biTmp = BigInt(yearStr); if(isNegative) biTmp = -biTmp; if(biTmp < int.min || biTmp > int.max) error(tokenStart, "Date's year is out of range. (Must fit within a 32-bit signed int.)"); auto year = biTmp.toInt(); biTmp = BigInt(monthStr); if(biTmp < 1 || biTmp > 12) error(tokenStart, "Date's month is out of range."); auto month = biTmp.toInt(); biTmp = BigInt(dayStr); if(biTmp < 1 || biTmp > 31) error(tokenStart, "Date's month is out of range."); auto day = biTmp.toInt(); return Date(year, month, day); } private DateTimeFrac makeDateTimeFrac( bool isNegative, Date date, string hourStr, string minuteStr, string secondStr, string millisecondStr ) { BigInt biTmp; biTmp = BigInt(hourStr); if(biTmp < int.min || biTmp > int.max) error(tokenStart, "Datetime's hour is out of range."); auto numHours = biTmp.toInt(); biTmp = BigInt(minuteStr); if(biTmp < 0 || biTmp > int.max) error(tokenStart, "Datetime's minute is out of range."); auto numMinutes = biTmp.toInt(); int numSeconds = 0; if(secondStr != "") { biTmp = BigInt(secondStr); if(biTmp < 0 || biTmp > int.max) error(tokenStart, "Datetime's second is out of range."); numSeconds = biTmp.toInt(); } int millisecond = 0; if(millisecondStr != "") { biTmp = BigInt(millisecondStr); if(biTmp < 0 || biTmp > int.max) error(tokenStart, "Datetime's millisecond is out of range."); millisecond = biTmp.toInt(); if(millisecondStr.length == 1) millisecond *= 100; else if(millisecondStr.length == 2) millisecond *= 10; } Duration fracSecs = millisecond.msecs; auto offset = hours(numHours) + minutes(numMinutes) + seconds(numSeconds); if(isNegative) { offset = -offset; fracSecs = -fracSecs; } return DateTimeFrac(DateTime(date) + offset, fracSecs); } private Duration makeDuration( bool isNegative, string dayStr, string hourStr, string minuteStr, string secondStr, string millisecondStr ) { BigInt biTmp; long day = 0; if(dayStr != "") { biTmp = BigInt(dayStr); if(biTmp < long.min || biTmp > long.max) error(tokenStart, "Time span's day is out of range."); day = biTmp.toLong(); } biTmp = BigInt(hourStr); if(biTmp < long.min || biTmp > long.max) error(tokenStart, "Time span's hour is out of range."); auto hour = biTmp.toLong(); biTmp = BigInt(minuteStr); if(biTmp < long.min || biTmp > long.max) error(tokenStart, "Time span's minute is out of range."); auto minute = biTmp.toLong(); biTmp = BigInt(secondStr); if(biTmp < long.min || biTmp > long.max) error(tokenStart, "Time span's second is out of range."); auto second = biTmp.toLong(); long millisecond = 0; if(millisecondStr != "") { biTmp = BigInt(millisecondStr); if(biTmp < long.min || biTmp > long.max) error(tokenStart, "Time span's millisecond is out of range."); millisecond = biTmp.toLong(); if(millisecondStr.length == 1) millisecond *= 100; else if(millisecondStr.length == 2) millisecond *= 10; } auto duration = dur!"days" (day) + dur!"hours" (hour) + dur!"minutes"(minute) + dur!"seconds"(second) + dur!"msecs" (millisecond); if(isNegative) duration = -duration; return duration; } // This has to reproduce some weird corner case behaviors from the // original Java version of SDL. So some of this may seem weird. private Nullable!Duration getTimeZoneOffset(string str) { if(str.length < 2) return Nullable!Duration(); // Unknown timezone if(str[0] != '+' && str[0] != '-') return Nullable!Duration(); // Unknown timezone auto isNegative = str[0] == '-'; string numHoursStr; string numMinutesStr; if(str[1] == ':') { numMinutesStr = str[1..$]; numHoursStr = ""; } else { numMinutesStr = str.find(':'); numHoursStr = str[1 .. $-numMinutesStr.length]; } long numHours = 0; long numMinutes = 0; bool isUnknown = false; try { switch(numHoursStr.length) { case 0: if(numMinutesStr.length == 3) { numHours = 0; numMinutes = to!long(numMinutesStr[1..$]); } else isUnknown = true; break; case 1: case 2: if(numMinutesStr.length == 0) { numHours = to!long(numHoursStr); numMinutes = 0; } else if(numMinutesStr.length == 3) { numHours = to!long(numHoursStr); numMinutes = to!long(numMinutesStr[1..$]); } else isUnknown = true; break; default: if(numMinutesStr.length == 0) { // Yes, this is correct numHours = 0; numMinutes = to!long(numHoursStr[1..$]); } else isUnknown = true; break; } } catch(ConvException e) isUnknown = true; if(isUnknown) return Nullable!Duration(); // Unknown timezone auto timeZoneOffset = hours(numHours) + minutes(numMinutes); if(isNegative) timeZoneOffset = -timeZoneOffset; // Timezone valid return Nullable!Duration(timeZoneOffset); } /// Lex date or datetime (after the initial numeric fragment was lexed) private void lexDate(bool isDateNegative, string yearStr) { assert(ch == '/'); // Lex months advanceChar(ErrorOnEOF.Yes); // Skip '/' auto monthStr = lexNumericFragment(); // Lex days if(ch != '/') error("Invalid date format: Missing days."); advanceChar(ErrorOnEOF.Yes); // Skip '/' auto dayStr = lexNumericFragment(); auto date = makeDate(isDateNegative, yearStr, monthStr, dayStr); if(!isEndOfNumber() && ch != '/') error("Dates cannot have suffixes."); // Date? if(isEOF) mixin(accept!("Value", "date")); auto endOfDate = location; while( !isEOF && ( ch == '\\' || ch == '/' || (isWhite(ch) && !isNewline(ch)) ) ) { if(ch == '\\' && hasNextCh && isNewline(nextCh)) { advanceChar(ErrorOnEOF.Yes); if(isAtNewline()) advanceChar(ErrorOnEOF.Yes); advanceChar(ErrorOnEOF.No); } eatWhite(); } // Date? if(isEOF || (!isDigit(ch) && ch != '-')) mixin(accept!("Value", "date", "", "endOfDate.index")); auto startOfTime = location; // Is time negative? bool isTimeNegative = ch == '-'; if(isTimeNegative) advanceChar(ErrorOnEOF.Yes); // Lex hours auto hourStr = ch == '.'? "" : lexNumericFragment(); // Lex minutes if(ch != ':') { // No minutes found. Therefore we had a plain Date followed // by a numeric literal, not a DateTime. lookaheadTokenInfo.exists = true; lookaheadTokenInfo.numericFragment = hourStr; lookaheadTokenInfo.isNegative = isTimeNegative; lookaheadTokenInfo.tokenStart = startOfTime; mixin(accept!("Value", "date", "", "endOfDate.index")); } advanceChar(ErrorOnEOF.Yes); // Skip ':' auto minuteStr = lexNumericFragment(); // Lex seconds, if exists string secondStr; if(ch == ':') { advanceChar(ErrorOnEOF.Yes); // Skip ':' secondStr = lexNumericFragment(); } // Lex milliseconds, if exists string millisecondStr; if(ch == '.') { advanceChar(ErrorOnEOF.Yes); // Skip '.' millisecondStr = lexNumericFragment(); } auto dateTimeFrac = makeDateTimeFrac(isTimeNegative, date, hourStr, minuteStr, secondStr, millisecondStr); // Lex zone, if exists if(ch == '-') { advanceChar(ErrorOnEOF.Yes); // Skip '-' auto timezoneStart = location; if(!isAlpha(ch)) error("Invalid timezone format."); while(!isEOF && !isWhite(ch)) advanceChar(ErrorOnEOF.No); auto timezoneStr = source[timezoneStart.index..location.index]; if(timezoneStr.startsWith("GMT")) { auto isoPart = timezoneStr["GMT".length..$]; auto offset = getTimeZoneOffset(isoPart); if(offset.isNull()) { // Unknown time zone mixin(accept!("Value", "DateTimeFracUnknownZone(dateTimeFrac.dateTime, dateTimeFrac.fracSecs, timezoneStr)")); } else { auto timezone = new immutable SimpleTimeZone(offset.get()); auto fsecs = dateTimeFrac.fracSecs; mixin(accept!("Value", "SysTime(dateTimeFrac.dateTime, fsecs, timezone)")); } } try { auto timezone = PosixTimeZone.getTimeZone(timezoneStr); if (timezone) { auto fsecs = dateTimeFrac.fracSecs; mixin(accept!("Value", "SysTime(dateTimeFrac.dateTime, fsecs, timezone)")); } } catch(TimeException e) { // Time zone not found. So just move along to "Unknown time zone" below. } // Unknown time zone mixin(accept!("Value", "DateTimeFracUnknownZone(dateTimeFrac.dateTime, dateTimeFrac.fracSecs, timezoneStr)")); } if(!isEndOfNumber()) error("Date-Times cannot have suffixes."); mixin(accept!("Value", "dateTimeFrac")); } /// Lex time span (after the initial numeric fragment was lexed) private void lexTimeSpan(bool isNegative, string firstPart) { assert(ch == ':' || ch == 'd'); string dayStr = ""; string hourStr; // Lexed days? bool hasDays = ch == 'd'; if(hasDays) { dayStr = firstPart; advanceChar(ErrorOnEOF.Yes); // Skip 'd' // Lex hours if(ch != ':') error("Invalid time span format: Missing hours."); advanceChar(ErrorOnEOF.Yes); // Skip ':' hourStr = lexNumericFragment(); } else hourStr = firstPart; // Lex minutes if(ch != ':') error("Invalid time span format: Missing minutes."); advanceChar(ErrorOnEOF.Yes); // Skip ':' auto minuteStr = lexNumericFragment(); // Lex seconds if(ch != ':') error("Invalid time span format: Missing seconds."); advanceChar(ErrorOnEOF.Yes); // Skip ':' auto secondStr = lexNumericFragment(); // Lex milliseconds, if exists string millisecondStr = ""; if(ch == '.') { advanceChar(ErrorOnEOF.Yes); // Skip '.' millisecondStr = lexNumericFragment(); } if(!isEndOfNumber()) error("Time spans cannot have suffixes."); auto duration = makeDuration(isNegative, dayStr, hourStr, minuteStr, secondStr, millisecondStr); mixin(accept!("Value", "duration")); } /// Advances past whitespace and comments private void eatWhite(bool allowComments=true) { // -- Comment/Whitepace Lexer ------------- enum State { normal, lineComment, // Got "#" or "//" or "--", Eating everything until newline blockComment, // Got "/*", Eating everything until "*/" } if(isEOF) return; Location commentStart; State state = State.normal; bool consumeNewlines = false; bool hasConsumedNewline = false; while(true) { final switch(state) { case State.normal: if(ch == '\\') { commentStart = location; consumeNewlines = true; hasConsumedNewline = false; } else if(ch == '#') { if(!allowComments) return; commentStart = location; state = State.lineComment; continue; } else if(ch == '/' || ch == '-') { commentStart = location; if(lookahead(ch)) { if(!allowComments) return; advanceChar(ErrorOnEOF.No); state = State.lineComment; continue; } else if(ch == '/' && lookahead('*')) { if(!allowComments) return; advanceChar(ErrorOnEOF.No); state = State.blockComment; continue; } else return; // Done } else if(isAtNewline()) { if(consumeNewlines) hasConsumedNewline = true; else return; // Done } else if(!isWhite(ch)) { if(consumeNewlines) { if(hasConsumedNewline) return; // Done else error("Only whitespace can come between a line-continuation backslash and the following newline."); } else return; // Done } break; case State.lineComment: if(lookahead(&isNewline)) state = State.normal; break; case State.blockComment: if(ch == '*' && lookahead('/')) { advanceChar(ErrorOnEOF.No); state = State.normal; } break; } advanceChar(ErrorOnEOF.No); if(isEOF) { // Reached EOF if(consumeNewlines && !hasConsumedNewline) error("Missing newline after line-continuation backslash."); else if(state == State.blockComment) error(commentStart, "Unterminated block comment."); else return; // Done, reached EOF } } } } version(sdlangUnittest) { import std.stdio; private auto loc = Location("filename", 0, 0, 0); private auto loc2 = Location("a", 1, 1, 1); unittest { assert([Token(symbol!"EOL",loc) ] == [Token(symbol!"EOL",loc) ] ); assert([Token(symbol!"EOL",loc,Value(7),"A")] == [Token(symbol!"EOL",loc2,Value(7),"B")] ); } private int numErrors = 0; private void testLex(string source, Token[] expected, bool test_locations = false, string file=__FILE__, size_t line=__LINE__) { Token[] actual; try actual = lexSource(source, "filename"); catch(SDLangParseException e) { numErrors++; stderr.writeln(file, "(", line, "): testLex failed on: ", source); stderr.writeln(" Expected:"); stderr.writeln(" ", expected); stderr.writeln(" Actual: SDLangParseException thrown:"); stderr.writeln(" ", e.msg); return; } bool is_same = actual == expected; if (is_same && test_locations) { is_same = actual.map!(t => t.location).equal(expected.map!(t => t.location)); } if(!is_same) { numErrors++; stderr.writeln(file, "(", line, "): testLex failed on: ", source); stderr.writeln(" Expected:"); stderr.writeln(" ", expected); stderr.writeln(" Actual:"); stderr.writeln(" ", actual); if(expected.length > 1 || actual.length > 1) { stderr.writeln(" expected.length: ", expected.length); stderr.writeln(" actual.length: ", actual.length); if(actual.length == expected.length) foreach(i; 0..actual.length) if(actual[i] != expected[i]) { stderr.writeln(" Unequal at index #", i, ":"); stderr.writeln(" Expected:"); stderr.writeln(" ", expected[i]); stderr.writeln(" Actual:"); stderr.writeln(" ", actual[i]); } } } } private void testLexThrows(string file=__FILE__, size_t line=__LINE__)(string source) { bool hadException = false; Token[] actual; try actual = lexSource(source, "filename"); catch(SDLangParseException e) hadException = true; if(!hadException) { numErrors++; stderr.writeln(file, "(", line, "): testLex failed on: ", source); stderr.writeln(" Expected SDLangParseException"); stderr.writeln(" Actual:"); stderr.writeln(" ", actual); } } } version(sdlangUnittest) unittest { writeln("Unittesting sdlang lexer..."); stdout.flush(); testLex("", []); testLex(" ", []); testLex("\\\n", []); testLex("/*foo*/", []); testLex("/* multiline \n comment */", []); testLex("/* * */", []); testLexThrows("/* "); testLex(":", [ Token(symbol!":", loc) ]); testLex("=", [ Token(symbol!"=", loc) ]); testLex("{", [ Token(symbol!"{", loc) ]); testLex("}", [ Token(symbol!"}", loc) ]); testLex(";", [ Token(symbol!"EOL",loc) ]); testLex("\n", [ Token(symbol!"EOL",loc) ]); testLex("foo", [ Token(symbol!"Ident",loc,Value(null),"foo") ]); testLex("_foo", [ Token(symbol!"Ident",loc,Value(null),"_foo") ]); testLex("foo.bar", [ Token(symbol!"Ident",loc,Value(null),"foo.bar") ]); testLex("foo-bar", [ Token(symbol!"Ident",loc,Value(null),"foo-bar") ]); testLex("foo.", [ Token(symbol!"Ident",loc,Value(null),"foo.") ]); testLex("foo-", [ Token(symbol!"Ident",loc,Value(null),"foo-") ]); testLexThrows(".foo"); testLex("foo bar", [ Token(symbol!"Ident",loc,Value(null),"foo"), Token(symbol!"Ident",loc,Value(null),"bar"), ]); testLex("foo \\ \n \n bar", [ Token(symbol!"Ident",loc,Value(null),"foo"), Token(symbol!"Ident",loc,Value(null),"bar"), ]); testLex("foo \\ \n \\ \n bar", [ Token(symbol!"Ident",loc,Value(null),"foo"), Token(symbol!"Ident",loc,Value(null),"bar"), ]); testLexThrows("foo \\ "); testLexThrows("foo \\ bar"); testLexThrows("foo \\ \n \\ "); testLexThrows("foo \\ \n \\ bar"); testLex("foo : = { } ; \n bar \n", [ Token(symbol!"Ident",loc,Value(null),"foo"), Token(symbol!":",loc), Token(symbol!"=",loc), Token(symbol!"{",loc), Token(symbol!"}",loc), Token(symbol!"EOL",loc), Token(symbol!"EOL",loc), Token(symbol!"Ident",loc,Value(null),"bar"), Token(symbol!"EOL",loc), ]); testLexThrows("<"); testLexThrows("*"); testLexThrows(`\`); // Integers testLex( "7", [ Token(symbol!"Value",loc,Value(cast( int) 7)) ]); testLex( "-7", [ Token(symbol!"Value",loc,Value(cast( int)-7)) ]); testLex( "7L", [ Token(symbol!"Value",loc,Value(cast(long) 7)) ]); testLex( "7l", [ Token(symbol!"Value",loc,Value(cast(long) 7)) ]); testLex("-7L", [ Token(symbol!"Value",loc,Value(cast(long)-7)) ]); testLex( "0", [ Token(symbol!"Value",loc,Value(cast( int) 0)) ]); testLex( "-0", [ Token(symbol!"Value",loc,Value(cast( int) 0)) ]); testLex("7/**/", [ Token(symbol!"Value",loc,Value(cast( int) 7)) ]); testLex("7#", [ Token(symbol!"Value",loc,Value(cast( int) 7)) ]); testLex("7 A", [ Token(symbol!"Value",loc,Value(cast(int)7)), Token(symbol!"Ident",loc,Value( null),"A"), ]); testLexThrows("7A"); testLexThrows("-A"); testLexThrows(`-""`); testLex("7;", [ Token(symbol!"Value",loc,Value(cast(int)7)), Token(symbol!"EOL",loc), ]); // Floats testLex("1.2F" , [ Token(symbol!"Value",loc,Value(cast( float)1.2)) ]); testLex("1.2f" , [ Token(symbol!"Value",loc,Value(cast( float)1.2)) ]); testLex("1.2" , [ Token(symbol!"Value",loc,Value(cast(double)1.2)) ]); testLex("1.2D" , [ Token(symbol!"Value",loc,Value(cast(double)1.2)) ]); testLex("1.2d" , [ Token(symbol!"Value",loc,Value(cast(double)1.2)) ]); testLex("1.2BD", [ Token(symbol!"Value",loc,Value(cast( real)1.2)) ]); testLex("1.2bd", [ Token(symbol!"Value",loc,Value(cast( real)1.2)) ]); testLex("1.2Bd", [ Token(symbol!"Value",loc,Value(cast( real)1.2)) ]); testLex("1.2bD", [ Token(symbol!"Value",loc,Value(cast( real)1.2)) ]); testLex(".2F" , [ Token(symbol!"Value",loc,Value(cast( float)0.2)) ]); testLex(".2" , [ Token(symbol!"Value",loc,Value(cast(double)0.2)) ]); testLex(".2D" , [ Token(symbol!"Value",loc,Value(cast(double)0.2)) ]); testLex(".2BD", [ Token(symbol!"Value",loc,Value(cast( real)0.2)) ]); testLex("-1.2F" , [ Token(symbol!"Value",loc,Value(cast( float)-1.2)) ]); testLex("-1.2" , [ Token(symbol!"Value",loc,Value(cast(double)-1.2)) ]); testLex("-1.2D" , [ Token(symbol!"Value",loc,Value(cast(double)-1.2)) ]); testLex("-1.2BD", [ Token(symbol!"Value",loc,Value(cast( real)-1.2)) ]); testLex("-.2F" , [ Token(symbol!"Value",loc,Value(cast( float)-0.2)) ]); testLex("-.2" , [ Token(symbol!"Value",loc,Value(cast(double)-0.2)) ]); testLex("-.2D" , [ Token(symbol!"Value",loc,Value(cast(double)-0.2)) ]); testLex("-.2BD", [ Token(symbol!"Value",loc,Value(cast( real)-0.2)) ]); testLex( "0.0" , [ Token(symbol!"Value",loc,Value(cast(double)0.0)) ]); testLex( "0.0F" , [ Token(symbol!"Value",loc,Value(cast( float)0.0)) ]); testLex( "0.0BD", [ Token(symbol!"Value",loc,Value(cast( real)0.0)) ]); testLex("-0.0" , [ Token(symbol!"Value",loc,Value(cast(double)0.0)) ]); testLex("-0.0F" , [ Token(symbol!"Value",loc,Value(cast( float)0.0)) ]); testLex("-0.0BD", [ Token(symbol!"Value",loc,Value(cast( real)0.0)) ]); testLex( "7F" , [ Token(symbol!"Value",loc,Value(cast( float)7.0)) ]); testLex( "7D" , [ Token(symbol!"Value",loc,Value(cast(double)7.0)) ]); testLex( "7BD" , [ Token(symbol!"Value",loc,Value(cast( real)7.0)) ]); testLex( "0F" , [ Token(symbol!"Value",loc,Value(cast( float)0.0)) ]); testLex( "0D" , [ Token(symbol!"Value",loc,Value(cast(double)0.0)) ]); testLex( "0BD" , [ Token(symbol!"Value",loc,Value(cast( real)0.0)) ]); testLex("-0F" , [ Token(symbol!"Value",loc,Value(cast( float)0.0)) ]); testLex("-0D" , [ Token(symbol!"Value",loc,Value(cast(double)0.0)) ]); testLex("-0BD" , [ Token(symbol!"Value",loc,Value(cast( real)0.0)) ]); testLex("1.2 F", [ Token(symbol!"Value",loc,Value(cast(double)1.2)), Token(symbol!"Ident",loc,Value( null),"F"), ]); testLexThrows("1.2A"); testLexThrows("1.2B"); testLexThrows("1.2BDF"); testLex("1.2;", [ Token(symbol!"Value",loc,Value(cast(double)1.2)), Token(symbol!"EOL",loc), ]); testLex("1.2F;", [ Token(symbol!"Value",loc,Value(cast(float)1.2)), Token(symbol!"EOL",loc), ]); testLex("1.2BD;", [ Token(symbol!"Value",loc,Value(cast(real)1.2)), Token(symbol!"EOL",loc), ]); // Booleans and null testLex("true", [ Token(symbol!"Value",loc,Value( true)) ]); testLex("false", [ Token(symbol!"Value",loc,Value(false)) ]); testLex("on", [ Token(symbol!"Value",loc,Value( true)) ]); testLex("off", [ Token(symbol!"Value",loc,Value(false)) ]); testLex("null", [ Token(symbol!"Value",loc,Value( null)) ]); testLex("TRUE", [ Token(symbol!"Ident",loc,Value(null),"TRUE") ]); testLex("true ", [ Token(symbol!"Value",loc,Value(true)) ]); testLex("true ", [ Token(symbol!"Value",loc,Value(true)) ]); testLex("tru", [ Token(symbol!"Ident",loc,Value(null),"tru") ]); testLex("truX", [ Token(symbol!"Ident",loc,Value(null),"truX") ]); testLex("trueX", [ Token(symbol!"Ident",loc,Value(null),"trueX") ]); // Raw Backtick Strings testLex("`hello world`", [ Token(symbol!"Value",loc,Value(`hello world` )) ]); testLex("` hello world `", [ Token(symbol!"Value",loc,Value(` hello world ` )) ]); testLex("`hello \\t world`", [ Token(symbol!"Value",loc,Value(`hello \t world`)) ]); testLex("`hello \\n world`", [ Token(symbol!"Value",loc,Value(`hello \n world`)) ]); testLex("`hello \n world`", [ Token(symbol!"Value",loc,Value("hello \n world")) ]); testLex("`hello \r\n world`", [ Token(symbol!"Value",loc,Value("hello \r\n world")) ]); testLex("`hello \"world\"`", [ Token(symbol!"Value",loc,Value(`hello "world"` )) ]); testLexThrows("`foo"); testLexThrows("`"); // Double-Quote Strings testLex(`"hello world"`, [ Token(symbol!"Value",loc,Value("hello world" )) ]); testLex(`" hello world "`, [ Token(symbol!"Value",loc,Value(" hello world " )) ]); testLex(`"hello \t world"`, [ Token(symbol!"Value",loc,Value("hello \t world")) ]); testLex(`"hello \n world"`, [ Token(symbol!"Value",loc,Value("hello \n world")) ]); testLex("\"hello \\\n world\"", [ Token(symbol!"Value",loc,Value("hello world" )) ]); testLex("\"hello \\ \n world\"", [ Token(symbol!"Value",loc,Value("hello world" )) ]); testLex("\"hello \\ \n\n world\"", [ Token(symbol!"Value",loc,Value("hello world" )) ]); testLex(`"\"hello world\""`, [ Token(symbol!"Value",loc,Value(`"hello world"` )) ]); testLexThrows("\"hello \n world\""); testLexThrows(`"foo`); testLexThrows(`"`); // Characters testLex("'a'", [ Token(symbol!"Value",loc,Value(cast(dchar) 'a')) ]); testLex("'\\n'", [ Token(symbol!"Value",loc,Value(cast(dchar)'\n')) ]); testLex("'\\t'", [ Token(symbol!"Value",loc,Value(cast(dchar)'\t')) ]); testLex("'\t'", [ Token(symbol!"Value",loc,Value(cast(dchar)'\t')) ]); testLex("'\\''", [ Token(symbol!"Value",loc,Value(cast(dchar)'\'')) ]); testLex(`'\\'`, [ Token(symbol!"Value",loc,Value(cast(dchar)'\\')) ]); testLexThrows("'a"); testLexThrows("'aa'"); testLexThrows("''"); testLexThrows("'\\\n'"); testLexThrows("'\n'"); testLexThrows(`'\`); testLexThrows(`'\'`); testLexThrows("'"); // Unicode testLex("日本語", [ Token(symbol!"Ident",loc,Value(null), "日本語") ]); testLex("`おはよう、日本。`", [ Token(symbol!"Value",loc,Value(`おはよう、日本。`)) ]); testLex(`"おはよう、日本。"`, [ Token(symbol!"Value",loc,Value(`おはよう、日本。`)) ]); testLex("'月'", [ Token(symbol!"Value",loc,Value("月"d.dup[0])) ]); // Base64 Binary testLex("[aGVsbG8gd29ybGQ=]", [ Token(symbol!"Value",loc,Value(cast(ubyte[])"hello world".dup))]); testLex("[ aGVsbG8gd29ybGQ= ]", [ Token(symbol!"Value",loc,Value(cast(ubyte[])"hello world".dup))]); testLex("[\n aGVsbG8g \n \n d29ybGQ= \n]", [ Token(symbol!"Value",loc,Value(cast(ubyte[])"hello world".dup))]); testLexThrows("[aGVsbG8gd29ybGQ]"); // Ie: Not multiple of 4 testLexThrows("[ aGVsbG8gd29ybGQ ]"); // Date testLex( "1999/12/5", [ Token(symbol!"Value",loc,Value(Date( 1999, 12, 5))) ]); testLex( "2013/2/22", [ Token(symbol!"Value",loc,Value(Date( 2013, 2, 22))) ]); testLex("-2013/2/22", [ Token(symbol!"Value",loc,Value(Date(-2013, 2, 22))) ]); testLexThrows("7/"); testLexThrows("2013/2/22a"); testLexThrows("2013/2/22f"); testLex("1999/12/5\n", [ Token(symbol!"Value",loc,Value(Date(1999, 12, 5))), Token(symbol!"EOL",loc), ]); // DateTime, no timezone testLex( "2013/2/22 07:53", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 0)))) ]); testLex( "2013/2/22 \t 07:53", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 0)))) ]); testLex( "2013/2/22/*foo*/07:53", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 0)))) ]); testLex( "2013/2/22 /*foo*/ \\\n /*bar*/ 07:53", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 0)))) ]); testLex( "2013/2/22 /*foo*/ \\\n\n \n /*bar*/ 07:53", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 0)))) ]); testLex( "2013/2/22 /*foo*/ \\\n\\\n \\\n /*bar*/ 07:53", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 0)))) ]); testLex( "2013/2/22/*foo*/\\\n/*bar*/07:53", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 0)))) ]); testLex("-2013/2/22 07:53", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime(-2013, 2, 22, 7, 53, 0)))) ]); testLex( "2013/2/22 -07:53", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 0, 0, 0) - hours(7) - minutes(53)))) ]); testLex("-2013/2/22 -07:53", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime(-2013, 2, 22, 0, 0, 0) - hours(7) - minutes(53)))) ]); testLex( "2013/2/22 07:53:34", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 34)))) ]); testLex( "2013/2/22 07:53:34.123", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 34), 123.msecs))) ]); testLex( "2013/2/22 07:53:34.12", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 34), 120.msecs))) ]); testLex( "2013/2/22 07:53:34.1", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 34), 100.msecs))) ]); testLex( "2013/2/22 07:53.123", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 0), 123.msecs))) ]); testLex( "2013/2/22 34:65", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 0, 0, 0) + hours(34) + minutes(65) + seconds( 0)))) ]); testLex( "2013/2/22 34:65:77.123", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 0, 0, 0) + hours(34) + minutes(65) + seconds(77), 123.msecs))) ]); testLex( "2013/2/22 34:65.123", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 0, 0, 0) + hours(34) + minutes(65) + seconds( 0), 123.msecs))) ]); testLex( "2013/2/22 -34:65", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 0, 0, 0) - hours(34) - minutes(65) - seconds( 0)))) ]); testLex( "2013/2/22 -34:65:77.123", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 0, 0, 0) - hours(34) - minutes(65) - seconds(77), -123.msecs))) ]); testLex( "2013/2/22 -34:65.123", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 0, 0, 0) - hours(34) - minutes(65) - seconds( 0), -123.msecs))) ]); testLexThrows("2013/2/22 07:53a"); testLexThrows("2013/2/22 07:53f"); testLexThrows("2013/2/22 07:53:34.123a"); testLexThrows("2013/2/22 07:53:34.123f"); testLexThrows("2013/2/22a 07:53"); testLex(`2013/2/22 "foo"`, [ Token(symbol!"Value",loc,Value(Date(2013, 2, 22))), Token(symbol!"Value",loc,Value("foo")), ]); testLex("2013/2/22 07", [ Token(symbol!"Value",loc,Value(Date(2013, 2, 22))), Token(symbol!"Value",loc,Value(cast(int)7)), ]); testLex("2013/2/22 1.2F", [ Token(symbol!"Value",loc,Value(Date(2013, 2, 22))), Token(symbol!"Value",loc,Value(cast(float)1.2)), ]); testLex("2013/2/22 .2F", [ Token(symbol!"Value",loc,Value(Date(2013, 2, 22))), Token(symbol!"Value",loc,Value(cast(float)0.2)), ]); testLex("2013/2/22 -1.2F", [ Token(symbol!"Value",loc,Value(Date(2013, 2, 22))), Token(symbol!"Value",loc,Value(cast(float)-1.2)), ]); testLex("2013/2/22 -.2F", [ Token(symbol!"Value",loc,Value(Date(2013, 2, 22))), Token(symbol!"Value",loc,Value(cast(float)-0.2)), ]); // DateTime, with known timezone testLex( "2013/2/22 07:53-GMT+00:00", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 7, 53, 0), new immutable SimpleTimeZone( hours(0) )))) ]); testLex("-2013/2/22 07:53-GMT+00:00", [ Token(symbol!"Value",loc,Value(SysTime(DateTime(-2013, 2, 22, 7, 53, 0), new immutable SimpleTimeZone( hours(0) )))) ]); testLex( "2013/2/22 -07:53-GMT+00:00", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 0, 0, 0) - hours(7) - minutes(53), new immutable SimpleTimeZone( hours(0) )))) ]); testLex("-2013/2/22 -07:53-GMT+00:00", [ Token(symbol!"Value",loc,Value(SysTime(DateTime(-2013, 2, 22, 0, 0, 0) - hours(7) - minutes(53), new immutable SimpleTimeZone( hours(0) )))) ]); testLex( "2013/2/22 07:53-GMT+02:10", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 7, 53, 0), new immutable SimpleTimeZone( hours(2)+minutes(10))))) ]); testLex( "2013/2/22 07:53-GMT-05:30", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 7, 53, 0), new immutable SimpleTimeZone(-hours(5)-minutes(30))))) ]); testLex( "2013/2/22 07:53:34-GMT+00:00", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 7, 53, 34), new immutable SimpleTimeZone( hours(0) )))) ]); testLex( "2013/2/22 07:53:34-GMT+02:10", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 7, 53, 34), new immutable SimpleTimeZone( hours(2)+minutes(10))))) ]); testLex( "2013/2/22 07:53:34-GMT-05:30", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 7, 53, 34), new immutable SimpleTimeZone(-hours(5)-minutes(30))))) ]); testLex( "2013/2/22 07:53:34.123-GMT+00:00", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 7, 53, 34), 123.msecs, new immutable SimpleTimeZone( hours(0) )))) ]); testLex( "2013/2/22 07:53:34.123-GMT+02:10", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 7, 53, 34), 123.msecs, new immutable SimpleTimeZone( hours(2)+minutes(10))))) ]); testLex( "2013/2/22 07:53:34.123-GMT-05:30", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 7, 53, 34), 123.msecs, new immutable SimpleTimeZone(-hours(5)-minutes(30))))) ]); testLex( "2013/2/22 07:53.123-GMT+00:00", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 7, 53, 0), 123.msecs, new immutable SimpleTimeZone( hours(0) )))) ]); testLex( "2013/2/22 07:53.123-GMT+02:10", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 7, 53, 0), 123.msecs, new immutable SimpleTimeZone( hours(2)+minutes(10))))) ]); testLex( "2013/2/22 07:53.123-GMT-05:30", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 7, 53, 0), 123.msecs, new immutable SimpleTimeZone(-hours(5)-minutes(30))))) ]); testLex( "2013/2/22 -34:65-GMT-05:30", [ Token(symbol!"Value",loc,Value(SysTime(DateTime( 2013, 2, 22, 0, 0, 0) - hours(34) - minutes(65) - seconds( 0), new immutable SimpleTimeZone(-hours(5)-minutes(30))))) ]); // DateTime, with Java SDL's occasionally weird interpretation of some // "not quite ISO" variations of the "GMT with offset" timezone strings. Token testTokenSimpleTimeZone(Duration d) { auto dateTime = DateTime(2013, 2, 22, 7, 53, 0); auto tz = new immutable SimpleTimeZone(d); return Token( symbol!"Value", loc, Value(SysTime(dateTime,tz)) ); } Token testTokenUnknownTimeZone(string tzName) { auto dateTime = DateTime(2013, 2, 22, 7, 53, 0); auto frac = 0.msecs; return Token( symbol!"Value", loc, Value(DateTimeFracUnknownZone(dateTime,frac,tzName)) ); } testLex("2013/2/22 07:53-GMT+", [ testTokenUnknownTimeZone("GMT+") ]); testLex("2013/2/22 07:53-GMT+:", [ testTokenUnknownTimeZone("GMT+:") ]); testLex("2013/2/22 07:53-GMT+:3", [ testTokenUnknownTimeZone("GMT+:3") ]); testLex("2013/2/22 07:53-GMT+:03", [ testTokenSimpleTimeZone(minutes(3)) ]); testLex("2013/2/22 07:53-GMT+:003", [ testTokenUnknownTimeZone("GMT+:003") ]); testLex("2013/2/22 07:53-GMT+4", [ testTokenSimpleTimeZone(hours(4)) ]); testLex("2013/2/22 07:53-GMT+4:", [ testTokenUnknownTimeZone("GMT+4:") ]); testLex("2013/2/22 07:53-GMT+4:3", [ testTokenUnknownTimeZone("GMT+4:3") ]); testLex("2013/2/22 07:53-GMT+4:03", [ testTokenSimpleTimeZone(hours(4)+minutes(3)) ]); testLex("2013/2/22 07:53-GMT+4:003", [ testTokenUnknownTimeZone("GMT+4:003") ]); testLex("2013/2/22 07:53-GMT+04", [ testTokenSimpleTimeZone(hours(4)) ]); testLex("2013/2/22 07:53-GMT+04:", [ testTokenUnknownTimeZone("GMT+04:") ]); testLex("2013/2/22 07:53-GMT+04:3", [ testTokenUnknownTimeZone("GMT+04:3") ]); testLex("2013/2/22 07:53-GMT+04:03", [ testTokenSimpleTimeZone(hours(4)+minutes(3)) ]); testLex("2013/2/22 07:53-GMT+04:03abc", [ testTokenUnknownTimeZone("GMT+04:03abc") ]); testLex("2013/2/22 07:53-GMT+04:003", [ testTokenUnknownTimeZone("GMT+04:003") ]); testLex("2013/2/22 07:53-GMT+004", [ testTokenSimpleTimeZone(minutes(4)) ]); testLex("2013/2/22 07:53-GMT+004:", [ testTokenUnknownTimeZone("GMT+004:") ]); testLex("2013/2/22 07:53-GMT+004:3", [ testTokenUnknownTimeZone("GMT+004:3") ]); testLex("2013/2/22 07:53-GMT+004:03", [ testTokenUnknownTimeZone("GMT+004:03") ]); testLex("2013/2/22 07:53-GMT+004:003", [ testTokenUnknownTimeZone("GMT+004:003") ]); testLex("2013/2/22 07:53-GMT+0004", [ testTokenSimpleTimeZone(minutes(4)) ]); testLex("2013/2/22 07:53-GMT+0004:", [ testTokenUnknownTimeZone("GMT+0004:") ]); testLex("2013/2/22 07:53-GMT+0004:3", [ testTokenUnknownTimeZone("GMT+0004:3") ]); testLex("2013/2/22 07:53-GMT+0004:03", [ testTokenUnknownTimeZone("GMT+0004:03") ]); testLex("2013/2/22 07:53-GMT+0004:003", [ testTokenUnknownTimeZone("GMT+0004:003") ]); testLex("2013/2/22 07:53-GMT+00004", [ testTokenSimpleTimeZone(minutes(4)) ]); testLex("2013/2/22 07:53-GMT+00004:", [ testTokenUnknownTimeZone("GMT+00004:") ]); testLex("2013/2/22 07:53-GMT+00004:3", [ testTokenUnknownTimeZone("GMT+00004:3") ]); testLex("2013/2/22 07:53-GMT+00004:03", [ testTokenUnknownTimeZone("GMT+00004:03") ]); testLex("2013/2/22 07:53-GMT+00004:003", [ testTokenUnknownTimeZone("GMT+00004:003") ]); // DateTime, with unknown timezone testLex( "2013/2/22 07:53-Bogus/Foo", [ Token(symbol!"Value",loc,Value(DateTimeFracUnknownZone(DateTime( 2013, 2, 22, 7, 53, 0), 0.msecs, "Bogus/Foo")), "2013/2/22 07:53-Bogus/Foo") ]); testLex("-2013/2/22 07:53-Bogus/Foo", [ Token(symbol!"Value",loc,Value(DateTimeFracUnknownZone(DateTime(-2013, 2, 22, 7, 53, 0), 0.msecs, "Bogus/Foo"))) ]); testLex( "2013/2/22 -07:53-Bogus/Foo", [ Token(symbol!"Value",loc,Value(DateTimeFracUnknownZone(DateTime( 2013, 2, 22, 0, 0, 0) - hours(7) - minutes(53), 0.msecs, "Bogus/Foo"))) ]); testLex("-2013/2/22 -07:53-Bogus/Foo", [ Token(symbol!"Value",loc,Value(DateTimeFracUnknownZone(DateTime(-2013, 2, 22, 0, 0, 0) - hours(7) - minutes(53), 0.msecs, "Bogus/Foo"))) ]); testLex( "2013/2/22 07:53:34-Bogus/Foo", [ Token(symbol!"Value",loc,Value(DateTimeFracUnknownZone(DateTime( 2013, 2, 22, 7, 53, 34), 0.msecs, "Bogus/Foo"))) ]); testLex( "2013/2/22 07:53:34.123-Bogus/Foo", [ Token(symbol!"Value",loc,Value(DateTimeFracUnknownZone(DateTime( 2013, 2, 22, 7, 53, 34), 123.msecs, "Bogus/Foo"))) ]); testLex( "2013/2/22 07:53.123-Bogus/Foo", [ Token(symbol!"Value",loc,Value(DateTimeFracUnknownZone(DateTime( 2013, 2, 22, 7, 53, 0), 123.msecs, "Bogus/Foo"))) ]); // Time Span testLex( "12:14:42", [ Token(symbol!"Value",loc,Value( days( 0)+hours(12)+minutes(14)+seconds(42)+msecs( 0))) ]); testLex("-12:14:42", [ Token(symbol!"Value",loc,Value(-days( 0)-hours(12)-minutes(14)-seconds(42)-msecs( 0))) ]); testLex( "00:09:12", [ Token(symbol!"Value",loc,Value( days( 0)+hours( 0)+minutes( 9)+seconds(12)+msecs( 0))) ]); testLex( "00:00:01.023", [ Token(symbol!"Value",loc,Value( days( 0)+hours( 0)+minutes( 0)+seconds( 1)+msecs( 23))) ]); testLex( "23d:05:21:23.532", [ Token(symbol!"Value",loc,Value( days(23)+hours( 5)+minutes(21)+seconds(23)+msecs(532))) ]); testLex( "23d:05:21:23.53", [ Token(symbol!"Value",loc,Value( days(23)+hours( 5)+minutes(21)+seconds(23)+msecs(530))) ]); testLex( "23d:05:21:23.5", [ Token(symbol!"Value",loc,Value( days(23)+hours( 5)+minutes(21)+seconds(23)+msecs(500))) ]); testLex("-23d:05:21:23.532", [ Token(symbol!"Value",loc,Value(-days(23)-hours( 5)-minutes(21)-seconds(23)-msecs(532))) ]); testLex("-23d:05:21:23.5", [ Token(symbol!"Value",loc,Value(-days(23)-hours( 5)-minutes(21)-seconds(23)-msecs(500))) ]); testLex( "23d:05:21:23", [ Token(symbol!"Value",loc,Value( days(23)+hours( 5)+minutes(21)+seconds(23)+msecs( 0))) ]); testLexThrows("12:14:42a"); testLexThrows("23d:05:21:23.532a"); testLexThrows("23d:05:21:23.532f"); // Combination testLex("foo. 7", [ Token(symbol!"Ident",loc,Value( null),"foo."), Token(symbol!"Value",loc,Value(cast(int)7)) ]); testLex(` namespace:person "foo" "bar" 1 23L name.first="ひとみ" name.last="Smith" { namespace:age 37; namespace:favorite_color "blue" // comment somedate 2013/2/22 07:53 -- comment inventory /* comment */ { socks } } `, [ Token(symbol!"EOL",loc,Value(null),"\n"), Token(symbol!"Ident", loc, Value( null ), "namespace"), Token(symbol!":", loc, Value( null ), ":"), Token(symbol!"Ident", loc, Value( null ), "person"), Token(symbol!"Value", loc, Value( "foo" ), `"foo"`), Token(symbol!"Value", loc, Value( "bar" ), `"bar"`), Token(symbol!"Value", loc, Value( cast( int) 1 ), "1"), Token(symbol!"Value", loc, Value( cast(long)23 ), "23L"), Token(symbol!"Ident", loc, Value( null ), "name.first"), Token(symbol!"=", loc, Value( null ), "="), Token(symbol!"Value", loc, Value( "ひとみ" ), `"ひとみ"`), Token(symbol!"Ident", loc, Value( null ), "name.last"), Token(symbol!"=", loc, Value( null ), "="), Token(symbol!"Value", loc, Value( "Smith" ), `"Smith"`), Token(symbol!"{", loc, Value( null ), "{"), Token(symbol!"EOL", loc, Value( null ), "\n"), Token(symbol!"Ident", loc, Value( null ), "namespace"), Token(symbol!":", loc, Value( null ), ":"), Token(symbol!"Ident", loc, Value( null ), "age"), Token(symbol!"Value", loc, Value( cast(int)37 ), "37"), Token(symbol!"EOL", loc, Value( null ), ";"), Token(symbol!"Ident", loc, Value( null ), "namespace"), Token(symbol!":", loc, Value( null ), ":"), Token(symbol!"Ident", loc, Value( null ), "favorite_color"), Token(symbol!"Value", loc, Value( "blue" ), `"blue"`), Token(symbol!"EOL", loc, Value( null ), "\n"), Token(symbol!"Ident", loc, Value( null ), "somedate"), Token(symbol!"Value", loc, Value( DateTimeFrac(DateTime(2013, 2, 22, 7, 53, 0)) ), "2013/2/22 07:53"), Token(symbol!"EOL", loc, Value( null ), "\n"), Token(symbol!"EOL", loc, Value( null ), "\n"), Token(symbol!"Ident", loc, Value(null), "inventory"), Token(symbol!"{", loc, Value(null), "{"), Token(symbol!"EOL", loc, Value(null), "\n"), Token(symbol!"Ident", loc, Value(null), "socks"), Token(symbol!"EOL", loc, Value(null), "\n"), Token(symbol!"}", loc, Value(null), "}"), Token(symbol!"EOL", loc, Value(null), "\n"), Token(symbol!"}", loc, Value(null), "}"), Token(symbol!"EOL", loc, Value(null), "\n"), ]); if(numErrors > 0) stderr.writeln(numErrors, " failed test(s)"); } version(sdlangUnittest) unittest { writeln("lexer: Regression test issue #8..."); stdout.flush(); testLex(`"\n \n"`, [ Token(symbol!"Value",loc,Value("\n \n"),`"\n \n"`) ]); testLex(`"\t\t"`, [ Token(symbol!"Value",loc,Value("\t\t"),`"\t\t"`) ]); testLex(`"\n\n"`, [ Token(symbol!"Value",loc,Value("\n\n"),`"\n\n"`) ]); } version(sdlangUnittest) unittest { writeln("lexer: Regression test issue #11..."); stdout.flush(); void test(string input) { testLex( input, [ Token(symbol!"EOL", loc, Value(null), "\n"), Token(symbol!"Ident",loc,Value(null), "a") ] ); } test("//X\na"); test("//\na"); test("--\na"); test("#\na"); } version(sdlangUnittest) unittest { writeln("lexer: Regression test issue #28..."); stdout.flush(); enum offset = 1; // workaround for an of-by-one error for line numbers testLex("test", [ Token(symbol!"Ident", Location("filename", 0, 0, 0), Value(null), "test") ], true); testLex("\ntest", [ Token(symbol!"EOL", Location("filename", 0, 0, 0), Value(null), "\n"), Token(symbol!"Ident", Location("filename", 1, 0, 1), Value(null), "test") ], true); testLex("\rtest", [ Token(symbol!"EOL", Location("filename", 0, 0, 0), Value(null), "\r"), Token(symbol!"Ident", Location("filename", 1, 0, 1), Value(null), "test") ], true); testLex("\r\ntest", [ Token(symbol!"EOL", Location("filename", 0, 0, 0), Value(null), "\r\n"), Token(symbol!"Ident", Location("filename", 1, 0, 2), Value(null), "test") ], true); testLex("\r\n\ntest", [ Token(symbol!"EOL", Location("filename", 0, 0, 0), Value(null), "\r\n"), Token(symbol!"EOL", Location("filename", 1, 0, 2), Value(null), "\n"), Token(symbol!"Ident", Location("filename", 2, 0, 3), Value(null), "test") ], true); testLex("\r\r\ntest", [ Token(symbol!"EOL", Location("filename", 0, 0, 0), Value(null), "\r"), Token(symbol!"EOL", Location("filename", 1, 0, 1), Value(null), "\r\n"), Token(symbol!"Ident", Location("filename", 2, 0, 3), Value(null), "test") ], true); } dub-1.19.0/source/dub/internal/sdlang/package.d000066400000000000000000000063301360435400500212540ustar00rootroot00000000000000// SDLang-D // Written in the D programming language. /++ $(H2 SDLang-D v0.9.3) Library for parsing and generating SDL (Simple Declarative Language). Import this module to use SDLang-D as a library. For the list of officially supported compiler versions, see the $(LINK2 https://github.com/Abscissa/SDLang-D/blob/master/.travis.yml, .travis.yml) file included with your version of SDLang-D. Links: $(UL $(LI $(LINK2 https://github.com/Abscissa/SDLang-D, SDLang-D Homepage) ) $(LI $(LINK2 http://semitwist.com/sdlang-d, SDLang-D API Reference (latest version) ) ) $(LI $(LINK2 http://semitwist.com/sdlang-d-docs, SDLang-D API Reference (earlier versions) ) ) $(LI $(LINK2 http://sdl.ikayzo.org/display/SDL/Language+Guide, Official SDL Site) [$(LINK2 http://semitwist.com/sdl-mirror/Language+Guide.html, mirror)] ) ) Authors: Nick Sabalausky ("Abscissa") http://semitwist.com/contact Copyright: Copyright (C) 2012-2015 Nick Sabalausky. License: $(LINK2 https://github.com/Abscissa/SDLang-D/blob/master/LICENSE.txt, zlib/libpng) +/ module dub.internal.sdlang; version (Have_sdlang_d) public import sdlang; else: import std.array; import std.datetime; import std.file; import std.stdio; import dub.internal.sdlang.ast; import dub.internal.sdlang.exception; import dub.internal.sdlang.lexer; import dub.internal.sdlang.parser; import dub.internal.sdlang.symbol; import dub.internal.sdlang.token; import dub.internal.sdlang.util; // Expose main public API public import dub.internal.sdlang.ast : Attribute, Tag; public import dub.internal.sdlang.exception; public import dub.internal.sdlang.parser : parseFile, parseSource; public import dub.internal.sdlang.token : Value, Token, DateTimeFrac, DateTimeFracUnknownZone; public import dub.internal.sdlang.util : sdlangVersion, Location; version(sdlangUnittest) void main() {} version(sdlangTestApp) { int main(string[] args) { if( args.length != 3 || (args[1] != "lex" && args[1] != "parse" && args[1] != "to-sdl") ) { stderr.writeln("SDLang-D v", sdlangVersion); stderr.writeln("Usage: sdlang [lex|parse|to-sdl] filename.sdl"); return 1; } auto filename = args[2]; try { if(args[1] == "lex") doLex(filename); else if(args[1] == "parse") doParse(filename); else doToSDL(filename); } catch(SDLangParseException e) { stderr.writeln(e.msg); return 1; } return 0; } void doLex(string filename) { auto source = cast(string)read(filename); auto lexer = new Lexer(source, filename); foreach(tok; lexer) { // Value string value; if(tok.symbol == symbol!"Value") value = tok.value.hasValue? toString(tok.value.type) : "{null}"; value = value==""? "\t" : "("~value~":"~tok.value.toString()~") "; // Data auto data = tok.data.replace("\n", "").replace("\r", ""); if(data != "") data = "\t|"~tok.data~"|"; // Display writeln( tok.location.toString, ":\t", tok.symbol.name, value, data ); if(tok.symbol.name == "Error") break; } } void doParse(string filename) { auto root = parseFile(filename); stdout.rawWrite(root.toDebugString()); writeln(); } void doToSDL(string filename) { auto root = parseFile(filename); stdout.rawWrite(root.toSDLDocument()); } } dub-1.19.0/source/dub/internal/sdlang/parser.d000066400000000000000000000317251360435400500211630ustar00rootroot00000000000000// SDLang-D // Written in the D programming language. module dub.internal.sdlang.parser; version (Have_sdlang_d) public import sdlang.parser; else: import std.file; import dub.internal.libInputVisitor; import dub.internal.sdlang.ast; import dub.internal.sdlang.exception; import dub.internal.sdlang.lexer; import dub.internal.sdlang.symbol; import dub.internal.sdlang.token; import dub.internal.sdlang.util; /// Returns root tag. Tag parseFile(string filename) { auto source = cast(string)read(filename); return parseSource(source, filename); } /// Returns root tag. The optional 'filename' parameter can be included /// so that the SDL document's filename (if any) can be displayed with /// any syntax error messages. Tag parseSource(string source, string filename=null) { auto lexer = new Lexer(source, filename); auto parser = DOMParser(lexer); return parser.parseRoot(); } /++ Parses an SDL document using StAX/Pull-style. Returns an InputRange with element type ParserEvent. The pullParseFile version reads a file and parses it, while pullParseSource parses a string passed in. The optional 'filename' parameter in pullParseSource can be included so that the SDL document's filename (if any) can be displayed with any syntax error messages. Warning! The FileStartEvent and FileEndEvent events *might* be removed later. See $(LINK https://github.com/Abscissa/SDLang-D/issues/17) Example: ------------------ parent 12 attr="q" { childA 34 childB 56 } lastTag ------------------ The ParserEvent sequence emitted for that SDL document would be as follows (indented for readability): ------------------ FileStartEvent TagStartEvent (parent) ValueEvent (12) AttributeEvent (attr, "q") TagStartEvent (childA) ValueEvent (34) TagEndEvent TagStartEvent (childB) ValueEvent (56) TagEndEvent TagEndEvent TagStartEvent (lastTag) TagEndEvent FileEndEvent ------------------ Example: ------------------ foreach(event; pullParseFile("stuff.sdl")) { import std.stdio; if(event.peek!FileStartEvent()) writeln("FileStartEvent, starting! "); else if(event.peek!FileEndEvent()) writeln("FileEndEvent, done! "); else if(auto e = event.peek!TagStartEvent()) writeln("TagStartEvent: ", e.namespace, ":", e.name, " @ ", e.location); else if(event.peek!TagEndEvent()) writeln("TagEndEvent"); else if(auto e = event.peek!ValueEvent()) writeln("ValueEvent: ", e.value); else if(auto e = event.peek!AttributeEvent()) writeln("AttributeEvent: ", e.namespace, ":", e.name, "=", e.value); else // Shouldn't happen throw new Exception("Received unknown parser event"); } ------------------ +/ auto pullParseFile(string filename) { auto source = cast(string)read(filename); return parseSource(source, filename); } ///ditto auto pullParseSource(string source, string filename=null) { auto lexer = new Lexer(source, filename); auto parser = PullParser(lexer); return inputVisitor!ParserEvent( parser ); } /// The element of the InputRange returned by pullParseFile and pullParseSource: alias ParserEvent = std.variant.Algebraic!( FileStartEvent, FileEndEvent, TagStartEvent, TagEndEvent, ValueEvent, AttributeEvent, ); /// Event: Start of file struct FileStartEvent { Location location; } /// Event: End of file struct FileEndEvent { Location location; } /// Event: Start of tag struct TagStartEvent { Location location; string namespace; string name; } /// Event: End of tag struct TagEndEvent { //Location location; } /// Event: Found a Value in the current tag struct ValueEvent { Location location; Value value; } /// Event: Found an Attribute in the current tag struct AttributeEvent { Location location; string namespace; string name; Value value; } // The actual pull parser private struct PullParser { private Lexer lexer; private struct IDFull { string namespace; string name; } private void error(string msg) { error(lexer.front.location, msg); } private void error(Location loc, string msg) { throw new SDLangParseException(loc, "Error: "~msg); } private InputVisitor!(PullParser, ParserEvent) v; void visit(InputVisitor!(PullParser, ParserEvent) v) { this.v = v; parseRoot(); } private void emit(Event)(Event event) { v.yield( ParserEvent(event) ); } /// ::= EOF (Lookaheads: Anything) private void parseRoot() { //trace("Starting parse of file: ", lexer.filename); //trace(__FUNCTION__, ": ::= EOF (Lookaheads: Anything)"); auto startLocation = Location(lexer.filename, 0, 0, 0); emit( FileStartEvent(startLocation) ); parseTags(); auto token = lexer.front; if(!token.matches!"EOF"()) error("Expected end-of-file, not " ~ token.symbol.name); emit( FileEndEvent(token.location) ); } /// ::= (Lookaheads: Ident Value) /// | EOL (Lookaheads: EOL) /// | {empty} (Lookaheads: Anything else, except '{') void parseTags() { //trace("Enter ", __FUNCTION__); while(true) { auto token = lexer.front; if(token.matches!"Ident"() || token.matches!"Value"()) { //trace(__FUNCTION__, ": ::= (Lookaheads: Ident Value)"); parseTag(); continue; } else if(token.matches!"EOL"()) { //trace(__FUNCTION__, ": ::= EOL (Lookaheads: EOL)"); lexer.popFront(); continue; } else if(token.matches!"{"()) { error("Anonymous tags must have at least one value. They cannot just have children and attributes only."); } else { //trace(__FUNCTION__, ": ::= {empty} (Lookaheads: Anything else, except '{')"); break; } } } /// /// ::= (Lookaheads: Ident) /// | (Lookaheads: Value) void parseTag() { auto token = lexer.front; if(token.matches!"Ident"()) { //trace(__FUNCTION__, ": ::= (Lookaheads: Ident)"); //trace("Found tag named: ", tag.fullName); auto id = parseIDFull(); emit( TagStartEvent(token.location, id.namespace, id.name) ); } else if(token.matches!"Value"()) { //trace(__FUNCTION__, ": ::= (Lookaheads: Value)"); //trace("Found anonymous tag."); emit( TagStartEvent(token.location, null, null) ); } else error("Expected tag name or value, not " ~ token.symbol.name); if(lexer.front.matches!"="()) error("Anonymous tags must have at least one value. They cannot just have attributes and children only."); parseValues(); parseAttributes(); parseOptChild(); parseTagTerminator(); emit( TagEndEvent() ); } /// ::= Ident (Lookaheads: Ident) IDFull parseIDFull() { auto token = lexer.front; if(token.matches!"Ident"()) { //trace(__FUNCTION__, ": ::= Ident (Lookaheads: Ident)"); lexer.popFront(); return parseIDSuffix(token.data); } else { error("Expected namespace or identifier, not " ~ token.symbol.name); assert(0); } } /// /// ::= ':' Ident (Lookaheads: ':') /// ::= {empty} (Lookaheads: Anything else) IDFull parseIDSuffix(string firstIdent) { auto token = lexer.front; if(token.matches!":"()) { //trace(__FUNCTION__, ": ::= ':' Ident (Lookaheads: ':')"); lexer.popFront(); token = lexer.front; if(token.matches!"Ident"()) { lexer.popFront(); return IDFull(firstIdent, token.data); } else { error("Expected name, not " ~ token.symbol.name); assert(0); } } else { //trace(__FUNCTION__, ": ::= {empty} (Lookaheads: Anything else)"); return IDFull("", firstIdent); } } /// /// ::= Value (Lookaheads: Value) /// | {empty} (Lookaheads: Anything else) void parseValues() { while(true) { auto token = lexer.front; if(token.matches!"Value"()) { //trace(__FUNCTION__, ": ::= Value (Lookaheads: Value)"); parseValue(); continue; } else { //trace(__FUNCTION__, ": ::= {empty} (Lookaheads: Anything else)"); break; } } } /// Handle Value terminals that aren't part of an attribute void parseValue() { auto token = lexer.front; if(token.matches!"Value"()) { //trace(__FUNCTION__, ": (Handle Value terminals that aren't part of an attribute)"); auto value = token.value; //trace("In tag '", parent.fullName, "', found value: ", value); emit( ValueEvent(token.location, value) ); lexer.popFront(); } else error("Expected value, not "~token.symbol.name); } /// /// ::= (Lookaheads: Ident) /// | {empty} (Lookaheads: Anything else) void parseAttributes() { while(true) { auto token = lexer.front; if(token.matches!"Ident"()) { //trace(__FUNCTION__, ": ::= (Lookaheads: Ident)"); parseAttribute(); continue; } else { //trace(__FUNCTION__, ": ::= {empty} (Lookaheads: Anything else)"); break; } } } /// ::= '=' Value (Lookaheads: Ident) void parseAttribute() { //trace(__FUNCTION__, ": ::= '=' Value (Lookaheads: Ident)"); auto token = lexer.front; if(!token.matches!"Ident"()) error("Expected attribute name, not "~token.symbol.name); auto id = parseIDFull(); token = lexer.front; if(!token.matches!"="()) error("Expected '=' after attribute name, not "~token.symbol.name); lexer.popFront(); token = lexer.front; if(!token.matches!"Value"()) error("Expected attribute value, not "~token.symbol.name); //trace("In tag '", parent.fullName, "', found attribute '", attr.fullName, "'"); emit( AttributeEvent(token.location, id.namespace, id.name, token.value) ); lexer.popFront(); } /// /// ::= '{' EOL '}' (Lookaheads: '{') /// | {empty} (Lookaheads: Anything else) void parseOptChild() { auto token = lexer.front; if(token.matches!"{") { //trace(__FUNCTION__, ": ::= '{' EOL '}' (Lookaheads: '{')"); lexer.popFront(); token = lexer.front; if(!token.matches!"EOL"()) error("Expected newline or semicolon after '{', not "~token.symbol.name); lexer.popFront(); parseTags(); token = lexer.front; if(!token.matches!"}"()) error("Expected '}' after child tags, not "~token.symbol.name); lexer.popFront(); } else { //trace(__FUNCTION__, ": ::= {empty} (Lookaheads: Anything else)"); // Do nothing, no error. } } /// /// ::= EOL (Lookahead: EOL) /// | {empty} (Lookahead: EOF) void parseTagTerminator() { auto token = lexer.front; if(token.matches!"EOL") { //trace(__FUNCTION__, ": ::= EOL (Lookahead: EOL)"); lexer.popFront(); } else if(token.matches!"EOF") { //trace(__FUNCTION__, ": ::= {empty} (Lookahead: EOF)"); // Do nothing } else error("Expected end of tag (newline, semicolon or end-of-file), not " ~ token.symbol.name); } } private struct DOMParser { Lexer lexer; Tag parseRoot() { auto currTag = new Tag(null, null, "root"); currTag.location = Location(lexer.filename, 0, 0, 0); auto parser = PullParser(lexer); auto eventRange = inputVisitor!ParserEvent( parser ); foreach(event; eventRange) { if(auto e = event.peek!TagStartEvent()) { auto newTag = new Tag(currTag, e.namespace, e.name); newTag.location = e.location; currTag = newTag; } else if(event.peek!TagEndEvent()) { currTag = currTag.parent; if(!currTag) parser.error("Internal Error: Received an extra TagEndEvent"); } else if(auto e = event.peek!ValueEvent()) { currTag.add(e.value); } else if(auto e = event.peek!AttributeEvent()) { auto attr = new Attribute(e.namespace, e.name, e.value, e.location); currTag.add(attr); } else if(event.peek!FileStartEvent()) { // Do nothing } else if(event.peek!FileEndEvent()) { // There shouldn't be another parent. if(currTag.parent) parser.error("Internal Error: Unexpected end of file, not enough TagEndEvent"); } else parser.error("Internal Error: Received unknown parser event"); } return currTag; } } // Other parser tests are part of the AST's tests over in the ast module. // Regression test, issue #16: https://github.com/Abscissa/SDLang-D/issues/16 version(sdlangUnittest) unittest { import std.stdio; writeln("parser: Regression test issue #16..."); stdout.flush(); // Shouldn't crash foreach(event; pullParseSource(`tag "data"`)) { event.peek!FileStartEvent(); } } // Regression test, issue #31: https://github.com/Abscissa/SDLang-D/issues/31 // "Escape sequence results in range violation error" version(sdlangUnittest) unittest { import std.stdio; writeln("parser: Regression test issue #31..."); stdout.flush(); // Shouldn't get a Range violation parseSource(`test "\"foo\""`); } dub-1.19.0/source/dub/internal/sdlang/symbol.d000066400000000000000000000021701360435400500211640ustar00rootroot00000000000000// SDLang-D // Written in the D programming language. module dub.internal.sdlang.symbol; version (Have_sdlang_d) public import sdlang.symbol; else: import std.algorithm; static immutable validSymbolNames = [ "Error", "EOF", "EOL", ":", "=", "{", "}", "Ident", "Value", ]; /// Use this to create a Symbol. Ex: symbol!"Value" or symbol!"=" /// Invalid names (such as symbol!"FooBar") are rejected at compile-time. template symbol(string name) { static assert(validSymbolNames.find(name), "Invalid Symbol: '"~name~"'"); immutable symbol = _symbol(name); } private Symbol _symbol(string name) { return Symbol(name); } /// Symbol is essentially the "type" of a Token. /// Token is like an instance of a Symbol. /// /// This only represents terminals. Nonterminal tokens aren't /// constructed since the AST is built directly during parsing. /// /// You can't create a Symbol directly. Instead, use the 'symbol' /// template. struct Symbol { private string _name; @property string name() { return _name; } @disable this(); private this(string name) { this._name = name; } string toString() { return _name; } } dub-1.19.0/source/dub/internal/sdlang/token.d000066400000000000000000000403231360435400500210010ustar00rootroot00000000000000// SDLang-D // Written in the D programming language. module dub.internal.sdlang.token; version (Have_sdlang_d) public import sdlang.token; else: import std.array; import std.base64; import std.conv; import std.datetime; import std.range; import std.string; import std.typetuple; import std.variant; import dub.internal.sdlang.symbol; import dub.internal.sdlang.util; /// DateTime doesn't support milliseconds, but SDL's "Date Time" type does. /// So this is needed for any SDL "Date Time" that doesn't include a time zone. struct DateTimeFrac { this(DateTime dt, Duration fs) { this.dateTime = dt; this.fracSecs = fs; } DateTime dateTime; Duration fracSecs; } /++ If a "Date Time" literal in the SDL file has a time zone that's not found in your system, you get one of these instead of a SysTime. (Because it's impossible to indicate "unknown time zone" with 'std.datetime.TimeZone'.) The difference between this and 'DateTimeFrac' is that 'DateTimeFrac' indicates that no time zone was specified in the SDL at all, whereas 'DateTimeFracUnknownZone' indicates that a time zone was specified but data for it could not be found on your system. +/ struct DateTimeFracUnknownZone { DateTime dateTime; Duration fracSecs; string timeZone; bool opEquals(const DateTimeFracUnknownZone b) const { return opEquals(b); } bool opEquals(ref const DateTimeFracUnknownZone b) const { return this.dateTime == b.dateTime && this.fracSecs == b.fracSecs && this.timeZone == b.timeZone; } } /++ SDL's datatypes map to D's datatypes as described below. Most are straightforward, but take special note of the date/time-related types. Boolean: bool Null: typeof(null) Unicode Character: dchar Double-Quote Unicode String: string Raw Backtick Unicode String: string Integer (32 bits signed): int Long Integer (64 bits signed): long Float (32 bits signed): float Double Float (64 bits signed): double Decimal (128+ bits signed): real Binary (standard Base64): ubyte[] Time Span: Duration Date (with no time at all): Date Date Time (no timezone): DateTimeFrac Date Time (with a known timezone): SysTime Date Time (with an unknown timezone): DateTimeFracUnknownZone +/ alias TypeTuple!( bool, string, dchar, int, long, float, double, real, Date, DateTimeFrac, SysTime, DateTimeFracUnknownZone, Duration, ubyte[], typeof(null), ) ValueTypes; alias Algebraic!( ValueTypes ) Value; ///ditto template isSDLSink(T) { enum isSink = isOutputRange!T && is(ElementType!(T)[] == string); } string toSDLString(T)(T value) if( is( T : Value ) || is( T : bool ) || is( T : string ) || is( T : dchar ) || is( T : int ) || is( T : long ) || is( T : float ) || is( T : double ) || is( T : real ) || is( T : Date ) || is( T : DateTimeFrac ) || is( T : SysTime ) || is( T : DateTimeFracUnknownZone ) || is( T : Duration ) || is( T : ubyte[] ) || is( T : typeof(null) ) ) { Appender!string sink; toSDLString(value, sink); return sink.data; } void toSDLString(Sink)(Value value, ref Sink sink) if(isOutputRange!(Sink,char)) { foreach(T; ValueTypes) { if(value.type == typeid(T)) { toSDLString( value.get!T(), sink ); return; } } throw new Exception("Internal SDLang-D error: Unhandled type of Value. Contains: "~value.toString()); } void toSDLString(Sink)(typeof(null) value, ref Sink sink) if(isOutputRange!(Sink,char)) { sink.put("null"); } void toSDLString(Sink)(bool value, ref Sink sink) if(isOutputRange!(Sink,char)) { sink.put(value? "true" : "false"); } //TODO: Figure out how to properly handle strings/chars containing lineSep or paraSep void toSDLString(Sink)(string value, ref Sink sink) if(isOutputRange!(Sink,char)) { sink.put('"'); // This loop is UTF-safe foreach(char ch; value) { if (ch == '\n') sink.put(`\n`); else if(ch == '\r') sink.put(`\r`); else if(ch == '\t') sink.put(`\t`); else if(ch == '\"') sink.put(`\"`); else if(ch == '\\') sink.put(`\\`); else sink.put(ch); } sink.put('"'); } void toSDLString(Sink)(dchar value, ref Sink sink) if(isOutputRange!(Sink,char)) { sink.put('\''); if (value == '\n') sink.put(`\n`); else if(value == '\r') sink.put(`\r`); else if(value == '\t') sink.put(`\t`); else if(value == '\'') sink.put(`\'`); else if(value == '\\') sink.put(`\\`); else sink.put(value); sink.put('\''); } void toSDLString(Sink)(int value, ref Sink sink) if(isOutputRange!(Sink,char)) { sink.put( "%s".format(value) ); } void toSDLString(Sink)(long value, ref Sink sink) if(isOutputRange!(Sink,char)) { sink.put( "%sL".format(value) ); } void toSDLString(Sink)(float value, ref Sink sink) if(isOutputRange!(Sink,char)) { sink.put( "%.10sF".format(value) ); } void toSDLString(Sink)(double value, ref Sink sink) if(isOutputRange!(Sink,char)) { sink.put( "%.30sD".format(value) ); } void toSDLString(Sink)(real value, ref Sink sink) if(isOutputRange!(Sink,char)) { sink.put( "%.30sBD".format(value) ); } void toSDLString(Sink)(Date value, ref Sink sink) if(isOutputRange!(Sink,char)) { sink.put(to!string(value.year)); sink.put('/'); sink.put(to!string(cast(int)value.month)); sink.put('/'); sink.put(to!string(value.day)); } void toSDLString(Sink)(DateTimeFrac value, ref Sink sink) if(isOutputRange!(Sink,char)) { toSDLString(value.dateTime.date, sink); sink.put(' '); sink.put("%.2s".format(value.dateTime.hour)); sink.put(':'); sink.put("%.2s".format(value.dateTime.minute)); if(value.dateTime.second != 0) { sink.put(':'); sink.put("%.2s".format(value.dateTime.second)); } if(value.fracSecs.total!"msecs" != 0) { sink.put('.'); sink.put("%.3s".format(value.fracSecs.total!"msecs")); } } void toSDLString(Sink)(SysTime value, ref Sink sink) if(isOutputRange!(Sink,char)) { auto dateTimeFrac = DateTimeFrac(cast(DateTime)value, value.fracSecs); toSDLString(dateTimeFrac, sink); sink.put("-"); auto tzString = value.timezone.name; // If name didn't exist, try abbreviation. // Note that according to std.datetime docs, on Windows the // stdName/dstName may not be properly abbreviated. version(Windows) {} else if(tzString == "") { auto tz = value.timezone; auto stdTime = value.stdTime; if(tz.hasDST()) tzString = tz.dstInEffect(stdTime)? tz.dstName : tz.stdName; else tzString = tz.stdName; } if(tzString == "") { auto offset = value.timezone.utcOffsetAt(value.stdTime); sink.put("GMT"); if(offset < seconds(0)) { sink.put("-"); offset = -offset; } else sink.put("+"); long hours, minutes; offset.split!("hours", "minutes")(hours, minutes); sink.put("%.2s".format(hours)); sink.put(":"); sink.put("%.2s".format(minutes)); } else sink.put(tzString); } void toSDLString(Sink)(DateTimeFracUnknownZone value, ref Sink sink) if(isOutputRange!(Sink,char)) { auto dateTimeFrac = DateTimeFrac(value.dateTime, value.fracSecs); toSDLString(dateTimeFrac, sink); sink.put("-"); sink.put(value.timeZone); } void toSDLString(Sink)(Duration value, ref Sink sink) if(isOutputRange!(Sink,char)) { if(value < seconds(0)) { sink.put("-"); value = -value; } auto days = value.total!"days"(); if(days != 0) { sink.put("%s".format(days)); sink.put("d:"); } long hours, minutes, seconds, msecs; value.split!("hours", "minutes", "seconds", "msecs")(hours, minutes, seconds, msecs); sink.put("%.2s".format(hours)); sink.put(':'); sink.put("%.2s".format(minutes)); sink.put(':'); sink.put("%.2s".format(seconds)); if(msecs != 0) { sink.put('.'); sink.put("%.3s".format(msecs)); } } void toSDLString(Sink)(ubyte[] value, ref Sink sink) if(isOutputRange!(Sink,char)) { sink.put('['); sink.put( Base64.encode(value) ); sink.put(']'); } /// This only represents terminals. Nonterminals aren't /// constructed since the AST is directly built during parsing. struct Token { Symbol symbol = dub.internal.sdlang.symbol.symbol!"Error"; /// The "type" of this token Location location; Value value; /// Only valid when 'symbol' is symbol!"Value", otherwise null string data; /// Original text from source @disable this(); this(Symbol symbol, Location location, Value value=Value(null), string data=null) { this.symbol = symbol; this.location = location; this.value = value; this.data = data; } /// Tokens with differing symbols are always unequal. /// Tokens with differing values are always unequal. /// Tokens with differing Value types are always unequal. /// Member 'location' is always ignored for comparison. /// Member 'data' is ignored for comparison *EXCEPT* when the symbol is Ident. bool opEquals(Token b) { return opEquals(b); } bool opEquals(ref Token b) ///ditto { if( this.symbol != b.symbol || this.value.type != b.value.type || this.value != b.value ) return false; if(this.symbol == .symbol!"Ident") return this.data == b.data; return true; } bool matches(string symbolName)() { return this.symbol == .symbol!symbolName; } } version(sdlangUnittest) unittest { import std.stdio; writeln("Unittesting sdlang token..."); stdout.flush(); auto loc = Location("", 0, 0, 0); auto loc2 = Location("a", 1, 1, 1); assert(Token(symbol!"EOL",loc) == Token(symbol!"EOL",loc )); assert(Token(symbol!"EOL",loc) == Token(symbol!"EOL",loc2)); assert(Token(symbol!":", loc) == Token(symbol!":", loc )); assert(Token(symbol!"EOL",loc) != Token(symbol!":", loc )); assert(Token(symbol!"EOL",loc,Value(null),"\n") == Token(symbol!"EOL",loc,Value(null),"\n")); assert(Token(symbol!"EOL",loc,Value(null),"\n") == Token(symbol!"EOL",loc,Value(null),";" )); assert(Token(symbol!"EOL",loc,Value(null),"A" ) == Token(symbol!"EOL",loc,Value(null),"B" )); assert(Token(symbol!":", loc,Value(null),"A" ) == Token(symbol!":", loc,Value(null),"BB")); assert(Token(symbol!"EOL",loc,Value(null),"A" ) != Token(symbol!":", loc,Value(null),"A" )); assert(Token(symbol!"Ident",loc,Value(null),"foo") == Token(symbol!"Ident",loc,Value(null),"foo")); assert(Token(symbol!"Ident",loc,Value(null),"foo") != Token(symbol!"Ident",loc,Value(null),"BAR")); assert(Token(symbol!"Value",loc,Value(null),"foo") == Token(symbol!"Value",loc, Value(null),"foo")); assert(Token(symbol!"Value",loc,Value(null),"foo") == Token(symbol!"Value",loc2,Value(null),"foo")); assert(Token(symbol!"Value",loc,Value(null),"foo") == Token(symbol!"Value",loc, Value(null),"BAR")); assert(Token(symbol!"Value",loc,Value( 7),"foo") == Token(symbol!"Value",loc, Value( 7),"BAR")); assert(Token(symbol!"Value",loc,Value( 7),"foo") != Token(symbol!"Value",loc, Value( "A"),"foo")); assert(Token(symbol!"Value",loc,Value( 7),"foo") != Token(symbol!"Value",loc, Value( 2),"foo")); assert(Token(symbol!"Value",loc,Value(cast(int)7)) != Token(symbol!"Value",loc, Value(cast(long)7))); assert(Token(symbol!"Value",loc,Value(cast(float)1.2)) != Token(symbol!"Value",loc, Value(cast(double)1.2))); } version(sdlangUnittest) unittest { import std.stdio; writeln("Unittesting sdlang Value.toSDLString()..."); stdout.flush(); // Bool and null assert(Value(null ).toSDLString() == "null"); assert(Value(true ).toSDLString() == "true"); assert(Value(false).toSDLString() == "false"); // Base64 Binary assert(Value(cast(ubyte[])"hello world".dup).toSDLString() == "[aGVsbG8gd29ybGQ=]"); // Integer assert(Value(cast( int) 7).toSDLString() == "7"); assert(Value(cast( int)-7).toSDLString() == "-7"); assert(Value(cast( int) 0).toSDLString() == "0"); assert(Value(cast(long) 7).toSDLString() == "7L"); assert(Value(cast(long)-7).toSDLString() == "-7L"); assert(Value(cast(long) 0).toSDLString() == "0L"); // Floating point assert(Value(cast(float) 1.5).toSDLString() == "1.5F"); assert(Value(cast(float)-1.5).toSDLString() == "-1.5F"); assert(Value(cast(float) 0).toSDLString() == "0F"); assert(Value(cast(double) 1.5).toSDLString() == "1.5D"); assert(Value(cast(double)-1.5).toSDLString() == "-1.5D"); assert(Value(cast(double) 0).toSDLString() == "0D"); assert(Value(cast(real) 1.5).toSDLString() == "1.5BD"); assert(Value(cast(real)-1.5).toSDLString() == "-1.5BD"); assert(Value(cast(real) 0).toSDLString() == "0BD"); // String assert(Value("hello" ).toSDLString() == `"hello"`); assert(Value(" hello ").toSDLString() == `" hello "`); assert(Value("" ).toSDLString() == `""`); assert(Value("hello \r\n\t\"\\ world").toSDLString() == `"hello \r\n\t\"\\ world"`); assert(Value("日本語").toSDLString() == `"日本語"`); // Chars assert(Value(cast(dchar) 'A').toSDLString() == `'A'`); assert(Value(cast(dchar)'\r').toSDLString() == `'\r'`); assert(Value(cast(dchar)'\n').toSDLString() == `'\n'`); assert(Value(cast(dchar)'\t').toSDLString() == `'\t'`); assert(Value(cast(dchar)'\'').toSDLString() == `'\''`); assert(Value(cast(dchar)'\\').toSDLString() == `'\\'`); assert(Value(cast(dchar) '月').toSDLString() == `'月'`); // Date assert(Value(Date( 2004,10,31)).toSDLString() == "2004/10/31"); assert(Value(Date(-2004,10,31)).toSDLString() == "-2004/10/31"); // DateTimeFrac w/o Frac assert(Value(DateTimeFrac(DateTime(2004,10,31, 14,30,15))).toSDLString() == "2004/10/31 14:30:15"); assert(Value(DateTimeFrac(DateTime(2004,10,31, 1, 2, 3))).toSDLString() == "2004/10/31 01:02:03"); assert(Value(DateTimeFrac(DateTime(-2004,10,31, 14,30,15))).toSDLString() == "-2004/10/31 14:30:15"); // DateTimeFrac w/ Frac assert(Value(DateTimeFrac(DateTime(2004,10,31, 14,30,15), 123.msecs)).toSDLString() == "2004/10/31 14:30:15.123"); assert(Value(DateTimeFrac(DateTime(2004,10,31, 14,30,15), 120.msecs)).toSDLString() == "2004/10/31 14:30:15.120"); assert(Value(DateTimeFrac(DateTime(2004,10,31, 14,30,15), 100.msecs)).toSDLString() == "2004/10/31 14:30:15.100"); assert(Value(DateTimeFrac(DateTime(2004,10,31, 14,30,15), 12.msecs)).toSDLString() == "2004/10/31 14:30:15.012"); assert(Value(DateTimeFrac(DateTime(2004,10,31, 14,30,15), 1.msecs)).toSDLString() == "2004/10/31 14:30:15.001"); assert(Value(DateTimeFrac(DateTime(-2004,10,31, 14,30,15), 123.msecs)).toSDLString() == "-2004/10/31 14:30:15.123"); // DateTimeFracUnknownZone assert(Value(DateTimeFracUnknownZone(DateTime(2004,10,31, 14,30,15), 123.msecs, "Foo/Bar")).toSDLString() == "2004/10/31 14:30:15.123-Foo/Bar"); // SysTime assert(Value(SysTime(DateTime(2004,10,31, 14,30,15), new immutable SimpleTimeZone( hours(0) ))).toSDLString() == "2004/10/31 14:30:15-GMT+00:00"); assert(Value(SysTime(DateTime(2004,10,31, 1, 2, 3), new immutable SimpleTimeZone( hours(0) ))).toSDLString() == "2004/10/31 01:02:03-GMT+00:00"); assert(Value(SysTime(DateTime(2004,10,31, 14,30,15), new immutable SimpleTimeZone( hours(2)+minutes(10) ))).toSDLString() == "2004/10/31 14:30:15-GMT+02:10"); assert(Value(SysTime(DateTime(2004,10,31, 14,30,15), new immutable SimpleTimeZone(-hours(5)-minutes(30) ))).toSDLString() == "2004/10/31 14:30:15-GMT-05:30"); assert(Value(SysTime(DateTime(2004,10,31, 14,30,15), new immutable SimpleTimeZone( hours(2)+minutes( 3) ))).toSDLString() == "2004/10/31 14:30:15-GMT+02:03"); assert(Value(SysTime(DateTime(2004,10,31, 14,30,15), 123.msecs, new immutable SimpleTimeZone( hours(0) ))).toSDLString() == "2004/10/31 14:30:15.123-GMT+00:00"); // Duration assert( "12:14:42" == Value( days( 0)+hours(12)+minutes(14)+seconds(42)+msecs( 0)).toSDLString()); assert("-12:14:42" == Value(-days( 0)-hours(12)-minutes(14)-seconds(42)-msecs( 0)).toSDLString()); assert( "00:09:12" == Value( days( 0)+hours( 0)+minutes( 9)+seconds(12)+msecs( 0)).toSDLString()); assert( "00:00:01.023" == Value( days( 0)+hours( 0)+minutes( 0)+seconds( 1)+msecs( 23)).toSDLString()); assert( "23d:05:21:23.532" == Value( days(23)+hours( 5)+minutes(21)+seconds(23)+msecs(532)).toSDLString()); assert( "23d:05:21:23.530" == Value( days(23)+hours( 5)+minutes(21)+seconds(23)+msecs(530)).toSDLString()); assert( "23d:05:21:23.500" == Value( days(23)+hours( 5)+minutes(21)+seconds(23)+msecs(500)).toSDLString()); assert("-23d:05:21:23.532" == Value(-days(23)-hours( 5)-minutes(21)-seconds(23)-msecs(532)).toSDLString()); assert("-23d:05:21:23.500" == Value(-days(23)-hours( 5)-minutes(21)-seconds(23)-msecs(500)).toSDLString()); assert( "23d:05:21:23" == Value( days(23)+hours( 5)+minutes(21)+seconds(23)+msecs( 0)).toSDLString()); } dub-1.19.0/source/dub/internal/sdlang/util.d000066400000000000000000000052001360435400500206310ustar00rootroot00000000000000// SDLang-D // Written in the D programming language. module dub.internal.sdlang.util; version (Have_sdlang_d) public import sdlang.util; else: import std.algorithm; import std.datetime; import std.stdio; import std.string; import dub.internal.sdlang.token; enum sdlangVersion = "0.9.1"; alias immutable(ubyte)[] ByteString; auto startsWith(T)(string haystack, T needle) if( is(T:ByteString) || is(T:string) ) { return std.algorithm.startsWith( cast(ByteString)haystack, cast(ByteString)needle ); } struct Location { string file; /// Filename (including path) int line; /// Zero-indexed int col; /// Zero-indexed, Tab counts as 1 size_t index; /// Index into the source this(int line, int col, int index) { this.line = line; this.col = col; this.index = index; } this(string file, int line, int col, int index) { this.file = file; this.line = line; this.col = col; this.index = index; } string toString() { return "%s(%s:%s)".format(file, line+1, col+1); } } void removeIndex(E)(ref E[] arr, ptrdiff_t index) { arr = arr[0..index] ~ arr[index+1..$]; } void trace(string file=__FILE__, size_t line=__LINE__, TArgs...)(TArgs args) { version(sdlangTrace) { writeln(file, "(", line, "): ", args); stdout.flush(); } } string toString(TypeInfo ti) { if (ti == typeid( bool )) return "bool"; else if(ti == typeid( string )) return "string"; else if(ti == typeid( dchar )) return "dchar"; else if(ti == typeid( int )) return "int"; else if(ti == typeid( long )) return "long"; else if(ti == typeid( float )) return "float"; else if(ti == typeid( double )) return "double"; else if(ti == typeid( real )) return "real"; else if(ti == typeid( Date )) return "Date"; else if(ti == typeid( DateTimeFrac )) return "DateTimeFrac"; else if(ti == typeid( DateTimeFracUnknownZone )) return "DateTimeFracUnknownZone"; else if(ti == typeid( SysTime )) return "SysTime"; else if(ti == typeid( Duration )) return "Duration"; else if(ti == typeid( ubyte[] )) return "ubyte[]"; else if(ti == typeid( typeof(null) )) return "null"; return "{unknown}"; } enum BOM { UTF8, /// UTF-8 UTF16LE, /// UTF-16 (little-endian) UTF16BE, /// UTF-16 (big-endian) UTF32LE, /// UTF-32 (little-endian) UTF32BE, /// UTF-32 (big-endian) } enum NBOM = __traits(allMembers, BOM).length; immutable ubyte[][NBOM] ByteOrderMarks = [ [0xEF, 0xBB, 0xBF], //UTF8 [0xFF, 0xFE], //UTF16LE [0xFE, 0xFF], //UTF16BE [0xFF, 0xFE, 0x00, 0x00], //UTF32LE [0x00, 0x00, 0xFE, 0xFF] //UTF32BE ]; dub-1.19.0/source/dub/internal/utils.d000066400000000000000000000467731360435400500175700ustar00rootroot00000000000000/** ... Copyright: © 2012 Matthias Dondorff License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Matthias Dondorff */ module dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.url; import dub.compilers.buildsettings : BuildSettings; import dub.version_; import core.time : Duration; import std.algorithm : canFind, startsWith; import std.array : appender, array; import std.conv : to; import std.exception : enforce; import std.file; import std.string : format; import std.process; import std.traits : isIntegral; version(DubUseCurl) { import std.net.curl; public import std.net.curl : HTTPStatusException; } private NativePath[] temporary_files; NativePath getTempDir() { return NativePath(std.file.tempDir()); } NativePath getTempFile(string prefix, string extension = null) { import std.uuid : randomUUID; import std.array: replace; string fileName = prefix ~ "-" ~ randomUUID.toString() ~ extension; if (extension !is null && extension == ".d") fileName = fileName.replace("-", "_"); auto path = getTempDir() ~ fileName; temporary_files ~= path; return path; } /** Obtain a lock for a file at the given path. If the file cannot be locked within the given duration, an exception is thrown. The file will be created if it does not yet exist. Deleting the file is not safe as another process could create a new file with the same name. The returned lock will get unlocked upon destruction. Params: path = path to file that gets locked timeout = duration after which locking failed Returns: The locked file or an Exception on timeout. */ auto lockFile(string path, Duration timeout) { import core.thread : Thread; import std.datetime, std.stdio : File; import std.algorithm : move; // Just a wrapper to hide (and destruct) the locked File. static struct LockFile { // The Lock can't be unlinked as someone could try to lock an already // opened fd while a new file with the same name gets created. // Exclusive filesystem locks (O_EXCL, mkdir) could be deleted but // aren't automatically freed when a process terminates, see #1149. private File f; } auto file = File(path, "w"); auto t0 = Clock.currTime(); auto dur = 1.msecs; while (true) { if (file.tryLock()) return LockFile(move(file)); enforce(Clock.currTime() - t0 < timeout, "Failed to lock '"~path~"'."); if (dur < 1024.msecs) // exponentially increase sleep time dur *= 2; Thread.sleep(dur); } } static ~this() { foreach (path; temporary_files) { auto spath = path.toNativeString(); if (spath.exists) std.file.remove(spath); } } bool isWritableDir(NativePath p, bool create_if_missing = false) { import std.random; auto fname = p ~ format("__dub_write_test_%08X", uniform(0, uint.max)); if (create_if_missing && !exists(p.toNativeString())) mkdirRecurse(p.toNativeString()); try openFile(fname, FileMode.createTrunc).close(); catch (Exception) return false; remove(fname.toNativeString()); return true; } Json jsonFromFile(NativePath file, bool silent_fail = false) { if( silent_fail && !existsFile(file) ) return Json.emptyObject; auto f = openFile(file.toNativeString(), FileMode.read); scope(exit) f.close(); auto text = stripUTF8Bom(cast(string)f.readAll()); return parseJsonString(text, file.toNativeString()); } /** Read package info file content from archive. File needs to be in root folder or in first sub folder. Params: zip = path to archive file fileName = Package file name Returns: package file content. */ string packageInfoFileFromZip(NativePath zip, out string fileName) { import std.zip : ZipArchive, ArchiveMember; import dub.package_ : packageInfoFiles; auto f = openFile(zip, FileMode.read); ubyte[] b = new ubyte[cast(size_t)f.size]; f.rawRead(b); f.close(); auto archive = new ZipArchive(b); alias PSegment = typeof (NativePath.init.head); foreach (ArchiveMember am; archive.directory) { auto path = NativePath(am.name).bySegment.array; foreach (fil; packageInfoFiles) { if ((path.length == 1 && path[0] == fil.filename) || (path.length == 2 && path[$-1].name == fil.filename)) { fileName = fil.filename; return stripUTF8Bom(cast(string) archive.expand(archive.directory[am.name])); } } } throw new Exception("No package descriptor found"); } void writeJsonFile(NativePath path, Json json) { auto f = openFile(path, FileMode.createTrunc); scope(exit) f.close(); f.writePrettyJsonString(json); } /// Performs a write->delete->rename sequence to atomically "overwrite" the destination file void atomicWriteJsonFile(NativePath path, Json json) { import std.random : uniform; auto tmppath = path.parentPath ~ format("%s.%s.tmp", path.head, uniform(0, int.max)); auto f = openFile(tmppath, FileMode.createTrunc); scope (failure) { f.close(); removeFile(tmppath); } f.writePrettyJsonString(json); f.close(); if (existsFile(path)) removeFile(path); moveFile(tmppath, path); } bool existsDirectory(NativePath path) { if( !existsFile(path) ) return false; auto fi = getFileInfo(path); return fi.isDirectory; } void runCommand(string command, string[string] env = null, string workDir = null) { runCommands((&command)[0 .. 1], env, workDir); } void runCommands(in string[] commands, string[string] env = null, string workDir = null) { import std.stdio : stdin, stdout, stderr, File; version(Windows) enum nullFile = "NUL"; else version(Posix) enum nullFile = "/dev/null"; else static assert(0); auto childStdout = stdout; auto childStderr = stderr; auto config = Config.retainStdout | Config.retainStderr; // Disable child's stdout/stderr depending on LogLevel auto logLevel = getLogLevel(); if(logLevel >= LogLevel.warn) childStdout = File(nullFile, "w"); if(logLevel >= LogLevel.none) childStderr = File(nullFile, "w"); foreach(cmd; commands){ logDiagnostic("Running %s", cmd); Pid pid; pid = spawnShell(cmd, stdin, childStdout, childStderr, env, config, workDir); auto exitcode = pid.wait(); enforce(exitcode == 0, "Command failed with exit code " ~ to!string(exitcode) ~ ": " ~ cmd); } } version (Have_vibe_d_http) public import vibe.http.common : HTTPStatusException; /** Downloads a file from the specified URL. Any redirects will be followed until the actual file resource is reached or if the redirection limit of 10 is reached. Note that only HTTP(S) is currently supported. The download times out if a connection cannot be established within `timeout` ms, or if the average transfer rate drops below 10 bytes / s for more than `timeout` seconds. Pass `0` as `timeout` to disable both timeout mechanisms. Note: Timeouts are only implemented when curl is used (DubUseCurl). */ void download(string url, string filename, uint timeout = 8) { version(DubUseCurl) { auto conn = HTTP(); setupHTTPClient(conn, timeout); logDebug("Storing %s...", url); std.net.curl.download(url, filename, conn); // workaround https://issues.dlang.org/show_bug.cgi?id=18318 auto sl = conn.statusLine; logDebug("Download %s %s", url, sl); if (sl.code / 100 != 2) throw new HTTPStatusException(sl.code, "Downloading %s failed with %d (%s).".format(url, sl.code, sl.reason)); } else version (Have_vibe_d_http) { import vibe.inet.urltransfer; vibe.inet.urltransfer.download(url, filename); } else assert(false); } /// ditto void download(URL url, NativePath filename, uint timeout = 8) { download(url.toString(), filename.toNativeString(), timeout); } /// ditto ubyte[] download(string url, uint timeout = 8) { version(DubUseCurl) { auto conn = HTTP(); setupHTTPClient(conn, timeout); logDebug("Getting %s...", url); return cast(ubyte[])get(url, conn); } else version (Have_vibe_d_http) { import vibe.inet.urltransfer; import vibe.stream.operations; ubyte[] ret; vibe.inet.urltransfer.download(url, (scope input) { ret = input.readAll(); }); return ret; } else assert(false); } /// ditto ubyte[] download(URL url, uint timeout = 8) { return download(url.toString(), timeout); } /** Downloads a file from the specified URL with retry logic. Downloads a file from the specified URL with up to n tries on failure Throws: `Exception` if the download failed or `HTTPStatusException` after the nth retry or on "unrecoverable failures" such as 404 not found Otherwise might throw anything else that `download` throws. See_Also: download The download times out if a connection cannot be established within `timeout` ms, or if the average transfer rate drops below 10 bytes / s for more than `timeout` seconds. Pass `0` as `timeout` to disable both timeout mechanisms. Note: Timeouts are only implemented when curl is used (DubUseCurl). **/ void retryDownload(URL url, NativePath filename, size_t retryCount = 3, uint timeout = 8) { foreach(i; 0..retryCount) { version(DubUseCurl) { try { download(url, filename, timeout); return; } catch(HTTPStatusException e) { if (e.status == 404) throw e; else { logDebug("Failed to download %s (Attempt %s of %s)", url, i + 1, retryCount); if (i == retryCount - 1) throw e; else continue; } } catch(CurlException e) { logDebug("Failed to download %s (Attempt %s of %s)", url, i + 1, retryCount); continue; } } else { try { download(url, filename); return; } catch(HTTPStatusException e) { if (e.status == 404) throw e; else { logDebug("Failed to download %s (Attempt %s of %s)", url, i + 1, retryCount); if (i == retryCount - 1) throw e; else continue; } } } } throw new Exception("Failed to download %s".format(url)); } ///ditto ubyte[] retryDownload(URL url, size_t retryCount = 3, uint timeout = 8) { foreach(i; 0..retryCount) { version(DubUseCurl) { try { return download(url, timeout); } catch(HTTPStatusException e) { if (e.status == 404) throw e; else { logDebug("Failed to download %s (Attempt %s of %s)", url, i + 1, retryCount); if (i == retryCount - 1) throw e; else continue; } } catch(CurlException e) { logDebug("Failed to download %s (Attempt %s of %s)", url, i + 1, retryCount); continue; } } else { try { return download(url); } catch(HTTPStatusException e) { if (e.status == 404) throw e; else { logDebug("Failed to download %s (Attempt %s of %s)", url, i + 1, retryCount); if (i == retryCount - 1) throw e; else continue; } } } } throw new Exception("Failed to download %s".format(url)); } /// Returns the current DUB version in semantic version format string getDUBVersion() { import dub.version_; import std.array : split, join; // convert version string to valid SemVer format auto verstr = dubVersion; if (verstr.startsWith("v")) verstr = verstr[1 .. $]; auto parts = verstr.split("-"); if (parts.length >= 3) { // detect GIT commit suffix if (parts[$-1].length == 8 && parts[$-1][1 .. $].isHexNumber() && parts[$-2].isNumber()) verstr = parts[0 .. $-2].join("-") ~ "+" ~ parts[$-2 .. $].join("-"); } return verstr; } /** Get current executable's path if running as DUB executable, or find a DUB executable if DUB is used as a library. For the latter, the following locations are checked in order: $(UL $(LI current working directory) $(LI same directory as `compilerBinary` (if supplied)) $(LI all components of the `$PATH` variable) ) Params: compilerBinary = optional path to a D compiler executable, used to locate DUB executable Returns: The path to a valid DUB executable Throws: an Exception if no valid DUB executable is found */ public string getDUBExePath(in string compilerBinary=null) { version(DubApplication) { import std.file : thisExePath; return thisExePath(); } else { // this must be dub as a library import std.algorithm : filter, map, splitter; import std.array : array; import std.file : exists, getcwd; import std.path : chainPath, dirName; import std.range : chain, only, take; import std.process : environment; version(Windows) { enum exeName = "dub.exe"; enum pathSep = ';'; } else { enum exeName = "dub"; enum pathSep = ':'; } auto dubLocs = only( getcwd().chainPath(exeName), compilerBinary.dirName.chainPath(exeName), ) .take(compilerBinary.length ? 2 : 1) .chain( environment.get("PATH", "") .splitter(pathSep) .map!(p => p.chainPath(exeName)) ) .filter!exists; enforce(!dubLocs.empty, "Could not find DUB executable"); return dubLocs.front.array; } } version(DubUseCurl) { void setupHTTPClient(ref HTTP conn, uint timeout) { static if( is(typeof(&conn.verifyPeer)) ) conn.verifyPeer = false; auto proxy = environment.get("http_proxy", null); if (proxy.length) conn.proxy = proxy; auto noProxy = environment.get("no_proxy", null); if (noProxy.length) conn.handle.set(CurlOption.noproxy, noProxy); conn.handle.set(CurlOption.encoding, ""); if (timeout) { // connection (TLS+TCP) times out after 8s conn.handle.set(CurlOption.connecttimeout, timeout); // transfers time out after 8s below 10 byte/s conn.handle.set(CurlOption.low_speed_limit, 10); conn.handle.set(CurlOption.low_speed_time, timeout); } conn.addRequestHeader("User-Agent", "dub/"~getDUBVersion()~" (std.net.curl; +https://github.com/rejectedsoftware/dub)"); } } string stripUTF8Bom(string str) { if( str.length >= 3 && str[0 .. 3] == [0xEF, 0xBB, 0xBF] ) return str[3 ..$]; return str; } private bool isNumber(string str) { foreach (ch; str) switch (ch) { case '0': .. case '9': break; default: return false; } return true; } private bool isHexNumber(string str) { foreach (ch; str) switch (ch) { case '0': .. case '9': break; case 'a': .. case 'f': break; case 'A': .. case 'F': break; default: return false; } return true; } /** Get the closest match of $(D input) in the $(D array), where $(D distance) is the maximum levenshtein distance allowed between the compared strings. Returns $(D null) if no closest match is found. */ string getClosestMatch(string[] array, string input, size_t distance) { import std.algorithm : countUntil, map, levenshteinDistance; import std.uni : toUpper; auto distMap = array.map!(elem => levenshteinDistance!((a, b) => toUpper(a) == toUpper(b))(elem, input)); auto idx = distMap.countUntil!(a => a <= distance); return (idx == -1) ? null : array[idx]; } /** Searches for close matches to input in range. R must be a range of strings Note: Sorts the strings range. Use std.range.indexed to avoid this... */ auto fuzzySearch(R)(R strings, string input){ import std.algorithm : levenshteinDistance, schwartzSort, partition3; import std.traits : isSomeString; import std.range : ElementType; static assert(isSomeString!(ElementType!R), "Cannot call fuzzy search on non string rang"); immutable threshold = input.length / 4; return strings.partition3!((a, b) => a.length + threshold < b.length)(input)[1] .schwartzSort!(p => levenshteinDistance(input.toUpper, p.toUpper)); } /** If T is a bitfield-style enum, this function returns a string range listing the names of all members included in the given value. Example: --------- enum Bits { none = 0, a = 1<<0, b = 1<<1, c = 1<<2, a_c = a | c, } assert( bitFieldNames(Bits.none).equals(["none"]) ); assert( bitFieldNames(Bits.a).equals(["a"]) ); assert( bitFieldNames(Bits.a_c).equals(["a", "c", "a_c"]) ); --------- */ auto bitFieldNames(T)(T value) if(is(T==enum) && isIntegral!T) { import std.algorithm : filter, map; import std.conv : to; import std.traits : EnumMembers; return [ EnumMembers!(T) ] .filter!(member => member==0? value==0 : (value & member) == member) .map!(member => to!string(member)); } bool isIdentChar(dchar ch) { import std.ascii : isAlphaNum; return isAlphaNum(ch) || ch == '_'; } string stripDlangSpecialChars(string s) { import std.array : appender; auto ret = appender!string(); foreach(ch; s) ret.put(isIdentChar(ch) ? ch : '_'); return ret.data; } string determineModuleName(BuildSettings settings, NativePath file, NativePath base_path) { import std.algorithm : map; import std.array : array; import std.range : walkLength; assert(base_path.absolute); if (!file.absolute) file = base_path ~ file; size_t path_skip = 0; foreach (ipath; settings.importPaths.map!(p => NativePath(p))) { if (!ipath.absolute) ipath = base_path ~ ipath; assert(!ipath.empty); if (file.startsWith(ipath) && ipath.bySegment.walkLength > path_skip) path_skip = ipath.bySegment.walkLength; } enforce(path_skip > 0, format("Source file '%s' not found in any import path.", file.toNativeString())); auto mpath = file.bySegment.array[path_skip .. $]; auto ret = appender!string; //search for module keyword in file string moduleName = getModuleNameFromFile(file.to!string); if(moduleName.length) return moduleName; //create module name from path foreach (i; 0 .. mpath.length) { import std.path; auto p = mpath[i].name; if (p == "package.d") break; if (i > 0) ret ~= "."; if (i+1 < mpath.length) ret ~= p; else ret ~= p.baseName(".d"); } return ret.data; } /** * Search for module keyword in D Code */ string getModuleNameFromContent(string content) { import std.regex; import std.string; content = content.strip; if (!content.length) return null; static bool regex_initialized = false; static Regex!char comments_pattern, module_pattern; if (!regex_initialized) { comments_pattern = regex(`//[^\r\n]*\r?\n?|/\*.*?\*/|/\+.*\+/`, "gs"); module_pattern = regex(`module\s+([\w\.]+)\s*;`, "g"); regex_initialized = true; } content = replaceAll(content, comments_pattern, " "); auto result = matchFirst(content, module_pattern); if (!result.empty) return result[1]; return null; } unittest { assert(getModuleNameFromContent("") == ""); assert(getModuleNameFromContent("module myPackage.myModule;") == "myPackage.myModule"); assert(getModuleNameFromContent("module \t\n myPackage.myModule \t\r\n;") == "myPackage.myModule"); assert(getModuleNameFromContent("// foo\nmodule bar;") == "bar"); assert(getModuleNameFromContent("/*\nfoo\n*/\nmodule bar;") == "bar"); assert(getModuleNameFromContent("/+\nfoo\n+/\nmodule bar;") == "bar"); assert(getModuleNameFromContent("/***\nfoo\n***/\nmodule bar;") == "bar"); assert(getModuleNameFromContent("/+++\nfoo\n+++/\nmodule bar;") == "bar"); assert(getModuleNameFromContent("// module foo;\nmodule bar;") == "bar"); assert(getModuleNameFromContent("/* module foo; */\nmodule bar;") == "bar"); assert(getModuleNameFromContent("/+ module foo; +/\nmodule bar;") == "bar"); assert(getModuleNameFromContent("/+ /+ module foo; +/ +/\nmodule bar;") == "bar"); assert(getModuleNameFromContent("// module foo;\nmodule bar; // module foo;") == "bar"); assert(getModuleNameFromContent("// module foo;\nmodule// module foo;\nbar//module foo;\n;// module foo;") == "bar"); assert(getModuleNameFromContent("/* module foo; */\nmodule/*module foo;*/bar/*module foo;*/;") == "bar", getModuleNameFromContent("/* module foo; */\nmodule/*module foo;*/bar/*module foo;*/;")); assert(getModuleNameFromContent("/+ /+ module foo; +/ module foo; +/ module bar;") == "bar"); //assert(getModuleNameFromContent("/+ /+ module foo; +/ module foo; +/ module bar/++/;") == "bar"); // nested comments require a context-free parser! assert(getModuleNameFromContent("/*\nmodule sometest;\n*/\n\nmodule fakemath;\n") == "fakemath"); } /** * Search for module keyword in file */ string getModuleNameFromFile(string filePath) { string fileContent = filePath.readText; logDiagnostic("Get module name from path: " ~ filePath); return getModuleNameFromContent(fileContent); } dub-1.19.0/source/dub/internal/vibecompat/000077500000000000000000000000001360435400500203735ustar00rootroot00000000000000dub-1.19.0/source/dub/internal/vibecompat/core/000077500000000000000000000000001360435400500213235ustar00rootroot00000000000000dub-1.19.0/source/dub/internal/vibecompat/core/file.d000066400000000000000000000200271360435400500224100ustar00rootroot00000000000000/** File handling. Copyright: © 2012 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.internal.vibecompat.core.file; public import dub.internal.vibecompat.inet.url; import dub.internal.vibecompat.core.log; import std.conv; import core.stdc.stdio; import std.datetime; import std.exception; import std.file; import std.path; import std.stdio; import std.string; import std.utf; /* Add output range support to File */ struct RangeFile { @safe: std.stdio.File file; void put(scope const ubyte[] bytes) @trusted { file.rawWrite(bytes); } void put(scope const char[] str) { put(cast(const(ubyte)[])str); } void put(char ch) @trusted { put((&ch)[0 .. 1]); } void put(dchar ch) { char[4] chars; put(chars[0 .. encode(chars, ch)]); } ubyte[] readAll() { auto sz = this.size; enforce(sz <= size_t.max, "File is too big to read to memory."); () @trusted { file.seek(0, SEEK_SET); } (); auto ret = new ubyte[cast(size_t)sz]; rawRead(ret); return ret; } void rawRead(ubyte[] dst) @trusted { enforce(file.rawRead(dst).length == dst.length, "Failed to readall bytes from file."); } void write(string str) { put(str); } void close() @trusted { file.close(); } void flush() @trusted { file.flush(); } @property ulong size() @trusted { return file.size; } } /** Opens a file stream with the specified mode. */ RangeFile openFile(NativePath path, FileMode mode = FileMode.read) { string fmode; final switch(mode){ case FileMode.read: fmode = "rb"; break; case FileMode.readWrite: fmode = "r+b"; break; case FileMode.createTrunc: fmode = "wb"; break; case FileMode.append: fmode = "ab"; break; } auto ret = std.stdio.File(path.toNativeString(), fmode); assert(ret.isOpen); return RangeFile(ret); } /// ditto RangeFile openFile(string path, FileMode mode = FileMode.read) { return openFile(NativePath(path), mode); } /** Moves or renames a file. */ void moveFile(NativePath from, NativePath to) { moveFile(from.toNativeString(), to.toNativeString()); } /// ditto void moveFile(string from, string to) { std.file.rename(from, to); } /** Copies a file. Note that attributes and time stamps are currently not retained. Params: from = NativePath of the source file to = NativePath for the destination file overwrite = If true, any file existing at the destination path will be overwritten. If this is false, an excpetion will be thrown should a file already exist at the destination path. Throws: An Exception if the copy operation fails for some reason. */ void copyFile(NativePath from, NativePath to, bool overwrite = false) { enforce(existsFile(from), "Source file does not exist."); if (existsFile(to)) { enforce(overwrite, "Destination file already exists."); // remove file before copy to allow "overwriting" files that are in // use on Linux removeFile(to); } static if (is(PreserveAttributes)) { .copy(from.toNativeString(), to.toNativeString(), PreserveAttributes.yes); } else { .copy(from.toNativeString(), to.toNativeString()); // try to preserve ownership/permissions in Posix version (Posix) { import core.sys.posix.sys.stat; import core.sys.posix.unistd; import std.utf; auto cspath = toUTFz!(const(char)*)(from.toNativeString()); auto cdpath = toUTFz!(const(char)*)(to.toNativeString()); stat_t st; enforce(stat(cspath, &st) == 0, "Failed to get attributes of source file."); if (chown(cdpath, st.st_uid, st.st_gid) != 0) st.st_mode &= ~(S_ISUID | S_ISGID); chmod(cdpath, st.st_mode); } } } /// ditto void copyFile(string from, string to) { copyFile(NativePath(from), NativePath(to)); } version (Windows) extern(Windows) int CreateHardLinkW(in wchar* to, in wchar* from, void* attr=null); // guess whether 2 files are identical, ignores filename and content private bool sameFile(NativePath a, NativePath b) { version (Posix) { auto st_a = std.file.DirEntry(a.toNativeString).statBuf; auto st_b = std.file.DirEntry(b.toNativeString).statBuf; return st_a == st_b; } else { static assert(__traits(allMembers, FileInfo)[0] == "name"); return getFileInfo(a).tupleof[1 .. $] == getFileInfo(b).tupleof[1 .. $]; } } /** Creates a hardlink. */ void hardLinkFile(NativePath from, NativePath to, bool overwrite = false) { if (existsFile(to)) { enforce(overwrite, "Destination file already exists."); if (auto fe = collectException!FileException(removeFile(to))) { if (sameFile(from, to)) return; throw fe; } } version (Windows) { alias cstr = toUTFz!(const(wchar)*); if (CreateHardLinkW(cstr(to.toNativeString), cstr(from.toNativeString))) return; } else { import core.sys.posix.unistd : link; alias cstr = toUTFz!(const(char)*); if (!link(cstr(from.toNativeString), cstr(to.toNativeString))) return; } // fallback to copy copyFile(from, to, overwrite); } /** Removes a file */ void removeFile(NativePath path) { removeFile(path.toNativeString()); } /// ditto void removeFile(string path) { std.file.remove(path); } /** Checks if a file exists */ bool existsFile(NativePath path) { return existsFile(path.toNativeString()); } /// ditto bool existsFile(string path) { return std.file.exists(path); } /** Stores information about the specified file/directory into 'info' Returns false if the file does not exist. */ FileInfo getFileInfo(NativePath path) { auto ent = std.file.DirEntry(path.toNativeString()); return makeFileInfo(ent); } /// ditto FileInfo getFileInfo(string path) { return getFileInfo(NativePath(path)); } /** Creates a new directory. */ void createDirectory(NativePath path) { mkdir(path.toNativeString()); } /// ditto void createDirectory(string path) { createDirectory(NativePath(path)); } /** Enumerates all files in the specified directory. */ void listDirectory(NativePath path, scope bool delegate(FileInfo info) del) { foreach( DirEntry ent; dirEntries(path.toNativeString(), SpanMode.shallow) ) if( !del(makeFileInfo(ent)) ) break; } /// ditto void listDirectory(string path, scope bool delegate(FileInfo info) del) { listDirectory(NativePath(path), del); } /// ditto int delegate(scope int delegate(ref FileInfo)) iterateDirectory(NativePath path) { int iterator(scope int delegate(ref FileInfo) del){ int ret = 0; listDirectory(path, (fi){ ret = del(fi); return ret == 0; }); return ret; } return &iterator; } /// ditto int delegate(scope int delegate(ref FileInfo)) iterateDirectory(string path) { return iterateDirectory(NativePath(path)); } /** Returns the current working directory. */ NativePath getWorkingDirectory() { return NativePath(std.file.getcwd()); } /** Contains general information about a file. */ struct FileInfo { /// Name of the file (not including the path) string name; /// Size of the file (zero for directories) ulong size; /// Time of the last modification SysTime timeModified; /// Time of creation (not available on all operating systems/file systems) SysTime timeCreated; /// True if this is a symlink to an actual file bool isSymlink; /// True if this is a directory or a symlink pointing to a directory bool isDirectory; } /** Specifies how a file is manipulated on disk. */ enum FileMode { /// The file is opened read-only. read, /// The file is opened for read-write random access. readWrite, /// The file is truncated if it exists and created otherwise and the opened for read-write access. createTrunc, /// The file is opened for appending data to it and created if it does not exist. append } /** Accesses the contents of a file as a stream. */ private FileInfo makeFileInfo(DirEntry ent) { FileInfo ret; ret.name = baseName(ent.name); if( ret.name.length == 0 ) ret.name = ent.name; assert(ret.name.length > 0); ret.isSymlink = ent.isSymlink; try { ret.isDirectory = ent.isDir; ret.size = ent.size; ret.timeModified = ent.timeLastModified; version(Windows) ret.timeCreated = ent.timeCreated; else ret.timeCreated = ent.timeLastModified; } catch (Exception e) { logDiagnostic("Failed to get extended file information for %s: %s", ret.name, e.msg); } return ret; } dub-1.19.0/source/dub/internal/vibecompat/core/log.d000066400000000000000000000046741360435400500222640ustar00rootroot00000000000000/** Central logging facility for vibe. Copyright: © 2012 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.internal.vibecompat.core.log; import std.array; import std.datetime; import std.format; import std.stdio; import core.thread; private { shared LogLevel s_minLevel = LogLevel.info; shared LogLevel s_logFileLevel; } /// Sets the minimum log level to be printed. void setLogLevel(LogLevel level) nothrow { s_minLevel = level; } LogLevel getLogLevel() { return s_minLevel; } /** Logs a message. Params: level = The log level for the logged message fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logDebug(T...)(string fmt, lazy T args) nothrow { log(LogLevel.debug_, fmt, args); } /// ditto void logDiagnostic(T...)(string fmt, lazy T args) nothrow { log(LogLevel.diagnostic, fmt, args); } /// ditto void logInfo(T...)(string fmt, lazy T args) nothrow { log(LogLevel.info, fmt, args); } /// ditto void logWarn(T...)(string fmt, lazy T args) nothrow { log(LogLevel.warn, fmt, args); } /// ditto void logError(T...)(string fmt, lazy T args) nothrow { log(LogLevel.error, fmt, args); } /// ditto void log(T...)(LogLevel level, string fmt, lazy T args) nothrow { if( level < s_minLevel ) return; string pref; final switch( level ){ case LogLevel.debug_: pref = "trc"; break; case LogLevel.diagnostic: pref = "dbg"; break; case LogLevel.info: pref = "INF"; break; case LogLevel.warn: pref = "WRN"; break; case LogLevel.error: pref = "ERR"; break; case LogLevel.fatal: pref = "FATAL"; break; case LogLevel.none: assert(false); } try { auto txt = appender!string(); txt.reserve(256); formattedWrite(txt, fmt, args); auto threadid = () @trusted { return cast(ulong)cast(void*)Thread.getThis(); } (); auto fiberid = () @trusted { return cast(ulong)cast(void*)Fiber.getThis(); } (); threadid ^= threadid >> 32; fiberid ^= fiberid >> 32; if (level >= s_minLevel) { File output; if (level == LogLevel.info) () @trusted { output = stdout; } (); else () @trusted { output = stderr; } (); if (output.isOpen) { output.writeln(txt.data); output.flush(); } } } catch( Exception e ){ // this is bad but what can we do.. debug assert(false, e.msg); } } /// Specifies the log level for a particular log message. enum LogLevel { debug_, diagnostic, info, warn, error, fatal, none } dub-1.19.0/source/dub/internal/vibecompat/data/000077500000000000000000000000001360435400500213045ustar00rootroot00000000000000dub-1.19.0/source/dub/internal/vibecompat/data/json.d000066400000000000000000002003741360435400500224300ustar00rootroot00000000000000/** JSON serialization and value handling. This module provides the Json struct for reading, writing and manipulating JSON values. De(serialization) of arbitrary D types is also supported and is recommended for handling JSON in performance sensitive applications. Copyright: © 2012-2015 RejectedSoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.internal.vibecompat.data.json; version (Have_vibe_d_data) public import vibe.data.json; else: import dub.internal.vibecompat.data.utils; public import dub.internal.vibecompat.data.serialization; public import std.json : JSONException; import std.algorithm : equal, min; import std.array; import std.conv; import std.datetime; import std.exception; import std.format; import std.range; import std.string : format; import std.traits; version = JsonLineNumbers; version = VibeJsonFieldNames; /******************************************************************************/ /* public types */ /******************************************************************************/ /** Represents a single JSON value. Json values can have one of the types defined in the Json.Type enum. They behave mostly like values in ECMA script in the way that you can transparently perform operations on them. However, strict typechecking is done, so that operations between differently typed JSON values will throw a JSONException. Additionally, an explicit cast or using get!() or to!() is required to convert a JSON value to the corresponding static D type. */ struct Json { private { // putting all fields in a union results in many false pointers leading to // memory leaks and, worse, std.algorithm.swap triggering an assertion // because of internal pointers. This crude workaround seems to fix // the issues. void*[2] m_data; ref inout(T) getDataAs(T)() inout { static assert(T.sizeof <= m_data.sizeof); return *cast(inout(T)*)m_data.ptr; } @property ref inout(long) m_int() inout { return getDataAs!long(); } @property ref inout(double) m_float() inout { return getDataAs!double(); } @property ref inout(bool) m_bool() inout { return getDataAs!bool(); } @property ref inout(string) m_string() inout { return getDataAs!string(); } @property ref inout(Json[string]) m_object() inout { return getDataAs!(Json[string])(); } @property ref inout(Json[]) m_array() inout { return getDataAs!(Json[])(); } Type m_type = Type.undefined; version (VibeJsonFieldNames) { uint m_magic = 0x1337f00d; // works around Appender bug (DMD BUG 10690/10859/11357) string m_name; string m_fileName; } } /** Represents the run time type of a JSON value. */ enum Type { undefined, /// A non-existent value in a JSON object null_, /// Null value bool_, /// Boolean value int_, /// 64-bit integer value float_, /// 64-bit floating point value string, /// UTF-8 string array, /// Array of JSON values object, /// JSON object aka. dictionary from string to Json Undefined = undefined, /// Compatibility alias - will be deprecated soon Null = null_, /// Compatibility alias - will be deprecated soon Bool = bool_, /// Compatibility alias - will be deprecated soon Int = int_, /// Compatibility alias - will be deprecated soon Float = float_, /// Compatibility alias - will be deprecated soon String = string, /// Compatibility alias - will be deprecated soon Array = array, /// Compatibility alias - will be deprecated soon Object = object /// Compatibility alias - will be deprecated soon } /// New JSON value of Type.Undefined static @property Json undefined() { return Json(); } /// New JSON value of Type.Object static @property Json emptyObject() { return Json(cast(Json[string])null); } /// New JSON value of Type.Array static @property Json emptyArray() { return Json(cast(Json[])null); } version(JsonLineNumbers) int line; /** Constructor for a JSON object. */ this(typeof(null)) { m_type = Type.null_; } /// ditto this(bool v) { m_type = Type.bool_; m_bool = v; } /// ditto this(byte v) { this(cast(long)v); } /// ditto this(ubyte v) { this(cast(long)v); } /// ditto this(short v) { this(cast(long)v); } /// ditto this(ushort v) { this(cast(long)v); } /// ditto this(int v) { this(cast(long)v); } /// ditto this(uint v) { this(cast(long)v); } /// ditto this(long v) { m_type = Type.int_; m_int = v; } /// ditto this(double v) { m_type = Type.float_; m_float = v; } /// ditto this(string v) { m_type = Type.string; m_string = v; } /// ditto this(Json[] v) { m_type = Type.array; m_array = v; } /// ditto this(Json[string] v) { m_type = Type.object; m_object = v; } /** Allows assignment of D values to a JSON value. */ ref Json opAssign(Json v) return { m_type = v.m_type; final switch(m_type){ case Type.undefined: m_string = null; break; case Type.null_: m_string = null; break; case Type.bool_: m_bool = v.m_bool; break; case Type.int_: m_int = v.m_int; break; case Type.float_: m_float = v.m_float; break; case Type.string: m_string = v.m_string; break; case Type.array: opAssign(v.m_array); break; case Type.object: opAssign(v.m_object); break; } return this; } /// ditto void opAssign(typeof(null)) { m_type = Type.null_; m_string = null; } /// ditto bool opAssign(bool v) { m_type = Type.bool_; m_bool = v; return v; } /// ditto int opAssign(int v) { m_type = Type.int_; m_int = v; return v; } /// ditto long opAssign(long v) { m_type = Type.int_; m_int = v; return v; } /// ditto double opAssign(double v) { m_type = Type.float_; m_float = v; return v; } /// ditto string opAssign(string v) { m_type = Type.string; m_string = v; return v; } /// ditto Json[] opAssign(Json[] v) { m_type = Type.array; m_array = v; version (VibeJsonFieldNames) { if (m_magic == 0x1337f00d) { foreach (idx, ref av; m_array) av.m_name = format("%s[%s]", m_name, idx); } else m_name = null; } return v; } /// ditto Json[string] opAssign(Json[string] v) { m_type = Type.object; m_object = v; version (VibeJsonFieldNames) { if (m_magic == 0x1337f00d) { foreach (key, ref av; m_object) av.m_name = format("%s.%s", m_name, key); } else m_name = null; } return v; } /** Allows removal of values from Type.Object Json objects. */ void remove(string item) { checkType!(Json[string])(); m_object.remove(item); } /** The current type id of this JSON object. */ @property Type type() const { return m_type; } /** Clones a JSON value recursively. */ Json clone() const { final switch (m_type) { case Type.undefined: return Json.undefined; case Type.null_: return Json(null); case Type.bool_: return Json(m_bool); case Type.int_: return Json(m_int); case Type.float_: return Json(m_float); case Type.string: return Json(m_string); case Type.array: auto ret = Json.emptyArray; foreach (v; this) ret ~= v.clone(); return ret; case Type.object: auto ret = Json.emptyObject; foreach (string name, v; this) ret[name] = v.clone(); return ret; } } /** Check whether the JSON object contains the given key and if yes, return a pointer to the corresponding object, otherwise return `null`. */ inout(Json*) opBinaryRight(string op : "in")(string key) inout { checkType!(Json[string])(); return key in m_object; } /** Allows direct indexing of array typed JSON values. */ ref inout(Json) opIndex(size_t idx) inout { checkType!(Json[])(); return m_array[idx]; } /// unittest { Json value = Json.emptyArray; value ~= 1; value ~= true; value ~= "foo"; assert(value[0] == 1); assert(value[1] == true); assert(value[2] == "foo"); } /** Allows direct indexing of object typed JSON values using a string as the key. */ const(Json) opIndex(string key) const { checkType!(Json[string])(); if( auto pv = key in m_object ) return *pv; Json ret = Json.undefined; ret.m_string = key; version (VibeJsonFieldNames) ret.m_name = format("%s.%s", m_name, key); return ret; } /// ditto ref Json opIndex(string key) { checkType!(Json[string])(); if( auto pv = key in m_object ) return *pv; if (m_object is null) { m_object = ["": Json.init]; m_object.remove(""); } m_object[key] = Json.init; assert(m_object !is null); assert(key in m_object, "Failed to insert key '"~key~"' into AA!?"); m_object[key].m_type = Type.undefined; // DMDBUG: AAs are the $H1T!!!11 assert(m_object[key].type == Type.undefined); m_object[key].m_string = key; version (VibeJsonFieldNames) m_object[key].m_name = format("%s.%s", m_name, key); return m_object[key]; } /// unittest { Json value = Json.emptyObject; value["a"] = 1; value["b"] = true; value["c"] = "foo"; assert(value["a"] == 1); assert(value["b"] == true); assert(value["c"] == "foo"); } /** Returns a slice of a JSON array. */ inout(Json[]) opSlice() inout { checkType!(Json[])(); return m_array; } /// inout(Json[]) opSlice(size_t from, size_t to) inout { checkType!(Json[])(); return m_array[from .. to]; } /** Returns the number of entries of string, array or object typed JSON values. */ @property size_t length() const { checkType!(string, Json[], Json[string])("property length"); switch(m_type){ case Type.string: return m_string.length; case Type.array: return m_array.length; case Type.object: return m_object.length; default: assert(false); } } /** Allows foreach iterating over JSON objects and arrays. */ int opApply(int delegate(ref Json obj) del) { checkType!(Json[], Json[string])("opApply"); if( m_type == Type.array ){ foreach( ref v; m_array ) if( auto ret = del(v) ) return ret; return 0; } else { foreach( ref v; m_object ) if( v.type != Type.undefined ) if( auto ret = del(v) ) return ret; return 0; } } /// ditto int opApply(int delegate(ref const Json obj) del) const { checkType!(Json[], Json[string])("opApply"); if( m_type == Type.array ){ foreach( ref v; m_array ) if( auto ret = del(v) ) return ret; return 0; } else { foreach( ref v; m_object ) if( v.type != Type.undefined ) if( auto ret = del(v) ) return ret; return 0; } } /// ditto int opApply(int delegate(ref size_t idx, ref Json obj) del) { checkType!(Json[])("opApply"); foreach( idx, ref v; m_array ) if( auto ret = del(idx, v) ) return ret; return 0; } /// ditto int opApply(int delegate(ref size_t idx, ref const Json obj) del) const { checkType!(Json[])("opApply"); foreach( idx, ref v; m_array ) if( auto ret = del(idx, v) ) return ret; return 0; } /// ditto int opApply(int delegate(ref string idx, ref Json obj) del) { checkType!(Json[string])("opApply"); foreach( idx, ref v; m_object ) if( v.type != Type.undefined ) if( auto ret = del(idx, v) ) return ret; return 0; } /// ditto int opApply(int delegate(ref string idx, ref const Json obj) del) const { checkType!(Json[string])("opApply"); foreach( idx, ref v; m_object ) if( v.type != Type.undefined ) if( auto ret = del(idx, v) ) return ret; return 0; } /** Converts the JSON value to the corresponding D type - types must match exactly. Available_Types: $(UL $(LI `bool` (`Type.bool_`)) $(LI `double` (`Type.float_`)) $(LI `float` (Converted from `double`)) $(LI `long` (`Type.int_`)) $(LI `ulong`, `int`, `uint`, `short`, `ushort`, `byte`, `ubyte` (Converted from `long`)) $(LI `string` (`Type.string`)) $(LI `Json[]` (`Type.array`)) $(LI `Json[string]` (`Type.object`)) ) See_Also: `opt`, `to`, `deserializeJson` */ inout(T) opCast(T)() inout { return get!T; } /// ditto @property inout(T) get(T)() inout { checkType!T(); static if (is(T == bool)) return m_bool; else static if (is(T == double)) return m_float; else static if (is(T == float)) return cast(T)m_float; else static if (is(T == long)) return m_int; else static if (is(T == ulong)) return cast(ulong)m_int; else static if (is(T : long)){ enforceJson(m_int <= T.max && m_int >= T.min, "Integer conversion out of bounds error", m_fileName, line); return cast(T)m_int; } else static if (is(T == string)) return m_string; else static if (is(T == Json[])) return m_array; else static if (is(T == Json[string])) return m_object; else static assert("JSON can only be cast to (bool, long, double, string, Json[] or Json[string]. Not "~T.stringof~"."); } /** Returns the native type for this JSON if it matches the current runtime type. If the runtime type does not match the given native type, the 'def' parameter is returned instead. See_Also: `get` */ @property const(T) opt(T)(const(T) def = T.init) const { if( typeId!T != m_type ) return def; return get!T; } /// ditto @property T opt(T)(T def = T.init) { if( typeId!T != m_type ) return def; return get!T; } /** Converts the JSON value to the corresponding D type - types are converted as necessary. Automatically performs conversions between strings and numbers. See `get` for the list of available types. For converting/deserializing JSON to complex data types see `deserializeJson`. See_Also: `get`, `deserializeJson` */ @property inout(T) to(T)() inout { static if( is(T == bool) ){ final switch( m_type ){ case Type.undefined: return false; case Type.null_: return false; case Type.bool_: return m_bool; case Type.int_: return m_int != 0; case Type.float_: return m_float != 0; case Type.string: return m_string.length > 0; case Type.array: return m_array.length > 0; case Type.object: return m_object.length > 0; } } else static if( is(T == double) ){ final switch( m_type ){ case Type.undefined: return T.init; case Type.null_: return 0; case Type.bool_: return m_bool ? 1 : 0; case Type.int_: return m_int; case Type.float_: return m_float; case Type.string: return .to!double(cast(string)m_string); case Type.array: return double.init; case Type.object: return double.init; } } else static if( is(T == float) ){ final switch( m_type ){ case Type.undefined: return T.init; case Type.null_: return 0; case Type.bool_: return m_bool ? 1 : 0; case Type.int_: return m_int; case Type.float_: return m_float; case Type.string: return .to!float(cast(string)m_string); case Type.array: return float.init; case Type.object: return float.init; } } else static if( is(T == long) ){ final switch( m_type ){ case Type.undefined: return 0; case Type.null_: return 0; case Type.bool_: return m_bool ? 1 : 0; case Type.int_: return m_int; case Type.float_: return cast(long)m_float; case Type.string: return .to!long(m_string); case Type.array: return 0; case Type.object: return 0; } } else static if( is(T : long) ){ final switch( m_type ){ case Type.undefined: return 0; case Type.null_: return 0; case Type.bool_: return m_bool ? 1 : 0; case Type.int_: return cast(T)m_int; case Type.float_: return cast(T)m_float; case Type.string: return cast(T).to!long(cast(string)m_string); case Type.array: return 0; case Type.object: return 0; } } else static if( is(T == string) ){ switch( m_type ){ default: return toString(); case Type.string: return m_string; } } else static if( is(T == Json[]) ){ switch( m_type ){ default: return Json([this]); case Type.array: return m_array; } } else static if( is(T == Json[string]) ){ switch( m_type ){ default: return Json(["value": this]); case Type.object: return m_object; } } else static assert("JSON can only be cast to (bool, long, double, string, Json[] or Json[string]. Not "~T.stringof~"."); } /** Performs unary operations on the JSON value. The following operations are supported for each type: $(DL $(DT Null) $(DD none) $(DT Bool) $(DD ~) $(DT Int) $(DD +, -, ++, --) $(DT Float) $(DD +, -, ++, --) $(DT String) $(DD none) $(DT Array) $(DD none) $(DT Object) $(DD none) ) */ Json opUnary(string op)() const { static if( op == "~" ){ checkType!bool(); return Json(~m_bool); } else static if( op == "+" || op == "-" || op == "++" || op == "--" ){ checkType!(long, double)("unary "~op); if( m_type == Type.int_ ) mixin("return Json("~op~"m_int);"); else if( m_type == Type.float_ ) mixin("return Json("~op~"m_float);"); else assert(false); } else static assert("Unsupported operator '"~op~"' for type JSON."); } /** Performs binary operations between JSON values. The two JSON values must be of the same run time type or a JSONException will be thrown. Only the operations listed are allowed for each of the types. $(DL $(DT Null) $(DD none) $(DT Bool) $(DD &&, ||) $(DT Int) $(DD +, -, *, /, %) $(DT Float) $(DD +, -, *, /, %) $(DT String) $(DD ~) $(DT Array) $(DD ~) $(DT Object) $(DD in) ) */ Json opBinary(string op)(ref const(Json) other) const { enforceJson(m_type == other.m_type, "Binary operation '"~op~"' between "~.to!string(m_type)~" and "~.to!string(other.m_type)~" JSON objects."); static if( op == "&&" ){ checkType!(bool)(op); return Json(m_bool && other.m_bool); } else static if( op == "||" ){ checkType!(bool)(op); return Json(m_bool || other.m_bool); } else static if( op == "+" ){ checkType!(long, double)(op); if( m_type == Type.Int ) return Json(m_int + other.m_int); else if( m_type == Type.float_ ) return Json(m_float + other.m_float); else assert(false); } else static if( op == "-" ){ checkType!(long, double)(op); if( m_type == Type.Int ) return Json(m_int - other.m_int); else if( m_type == Type.float_ ) return Json(m_float - other.m_float); else assert(false); } else static if( op == "*" ){ checkType!(long, double)(op); if( m_type == Type.Int ) return Json(m_int * other.m_int); else if( m_type == Type.float_ ) return Json(m_float * other.m_float); else assert(false); } else static if( op == "/" ){ checkType!(long, double)(op); if( m_type == Type.Int ) return Json(m_int / other.m_int); else if( m_type == Type.float_ ) return Json(m_float / other.m_float); else assert(false); } else static if( op == "%" ){ checkType!(long, double)(op); if( m_type == Type.Int ) return Json(m_int % other.m_int); else if( m_type == Type.float_ ) return Json(m_float % other.m_float); else assert(false); } else static if( op == "~" ){ checkType!(string, Json[])(op); if( m_type == Type.string ) return Json(m_string ~ other.m_string); else if (m_type == Type.array) return Json(m_array ~ other.m_array); else assert(false); } else static assert("Unsupported operator '"~op~"' for type JSON."); } /// ditto Json opBinary(string op)(Json other) if( op == "~" ) { static if( op == "~" ){ checkType!(string, Json[])(op); if( m_type == Type.string ) return Json(m_string ~ other.m_string); else if( m_type == Type.array ) return Json(m_array ~ other.m_array); else assert(false); } else static assert("Unsupported operator '"~op~"' for type JSON."); } /// ditto void opOpAssign(string op)(Json other) if (op == "+" || op == "-" || op == "*" || op == "/" || op == "%" || op =="~") { enforceJson(m_type == other.m_type || op == "~" && m_type == Type.array, "Binary operation '"~op~"=' between "~.to!string(m_type)~" and "~.to!string(other.m_type)~" JSON objects."); static if( op == "+" ){ if( m_type == Type.int_ ) m_int += other.m_int; else if( m_type == Type.float_ ) m_float += other.m_float; else enforceJson(false, "'+=' only allowed for scalar types, not "~.to!string(m_type)~"."); } else static if( op == "-" ){ if( m_type == Type.int_ ) m_int -= other.m_int; else if( m_type == Type.float_ ) m_float -= other.m_float; else enforceJson(false, "'-=' only allowed for scalar types, not "~.to!string(m_type)~"."); } else static if( op == "*" ){ if( m_type == Type.int_ ) m_int *= other.m_int; else if( m_type == Type.float_ ) m_float *= other.m_float; else enforceJson(false, "'*=' only allowed for scalar types, not "~.to!string(m_type)~"."); } else static if( op == "/" ){ if( m_type == Type.int_ ) m_int /= other.m_int; else if( m_type == Type.float_ ) m_float /= other.m_float; else enforceJson(false, "'/=' only allowed for scalar types, not "~.to!string(m_type)~"."); } else static if( op == "%" ){ if( m_type == Type.int_ ) m_int %= other.m_int; else if( m_type == Type.float_ ) m_float %= other.m_float; else enforceJson(false, "'%=' only allowed for scalar types, not "~.to!string(m_type)~"."); } else static if( op == "~" ){ if (m_type == Type.string) m_string ~= other.m_string; else if (m_type == Type.array) { if (other.m_type == Type.array) m_array ~= other.m_array; else appendArrayElement(other); } else enforceJson(false, "'~=' only allowed for string and array types, not "~.to!string(m_type)~"."); } else static assert("Unsupported operator '"~op~"=' for type JSON."); } /// ditto void opOpAssign(string op, T)(T other) if (!is(T == Json) && is(typeof(Json(other)))) { opOpAssign!op(Json(other)); } /// ditto Json opBinary(string op)(bool other) const { checkType!bool(); mixin("return Json(m_bool "~op~" other);"); } /// ditto Json opBinary(string op)(long other) const { checkType!long(); mixin("return Json(m_int "~op~" other);"); } /// ditto Json opBinary(string op)(double other) const { checkType!double(); mixin("return Json(m_float "~op~" other);"); } /// ditto Json opBinary(string op)(string other) const { checkType!string(); mixin("return Json(m_string "~op~" other);"); } /// ditto Json opBinary(string op)(Json[] other) { checkType!(Json[])(); mixin("return Json(m_array "~op~" other);"); } /// ditto Json opBinaryRight(string op)(bool other) const { checkType!bool(); mixin("return Json(other "~op~" m_bool);"); } /// ditto Json opBinaryRight(string op)(long other) const { checkType!long(); mixin("return Json(other "~op~" m_int);"); } /// ditto Json opBinaryRight(string op)(double other) const { checkType!double(); mixin("return Json(other "~op~" m_float);"); } /// ditto Json opBinaryRight(string op)(string other) const if(op == "~") { checkType!string(); return Json(other ~ m_string); } /// ditto inout(Json)* opBinaryRight(string op)(string other) inout if(op == "in") { checkType!(Json[string])(); auto pv = other in m_object; if( !pv ) return null; if( pv.type == Type.undefined ) return null; return pv; } /// ditto Json opBinaryRight(string op)(Json[] other) { checkType!(Json[])(); mixin("return Json(other "~op~" m_array);"); } /** * The append operator will append arrays. This method always appends it's argument as an array element, so nested arrays can be created. */ void appendArrayElement(Json element) { enforceJson(m_type == Type.array, "'appendArrayElement' only allowed for array types, not "~.to!string(m_type)~"."); m_array ~= element; } /** Compares two JSON values for equality. If the two values have different types, they are considered unequal. This differs with ECMA script, which performs a type conversion before comparing the values. */ bool opEquals(ref const Json other) const { if( m_type != other.m_type ) return false; final switch(m_type){ case Type.undefined: return false; case Type.null_: return true; case Type.bool_: return m_bool == other.m_bool; case Type.int_: return m_int == other.m_int; case Type.float_: return m_float == other.m_float; case Type.string: return m_string == other.m_string; case Type.array: return m_array == other.m_array; case Type.object: return m_object == other.m_object; } } /// ditto bool opEquals(const Json other) const { return opEquals(other); } /// ditto bool opEquals(typeof(null)) const { return m_type == Type.null_; } /// ditto bool opEquals(bool v) const { return m_type == Type.bool_ && m_bool == v; } /// ditto bool opEquals(int v) const { return m_type == Type.int_ && m_int == v; } /// ditto bool opEquals(long v) const { return m_type == Type.int_ && m_int == v; } /// ditto bool opEquals(double v) const { return m_type == Type.float_ && m_float == v; } /// ditto bool opEquals(string v) const { return m_type == Type.string && m_string == v; } /** Compares two JSON values. If the types of the two values differ, the value with the smaller type id is considered the smaller value. This differs from ECMA script, which performs a type conversion before comparing the values. JSON values of type Object cannot be compared and will throw an exception. */ int opCmp(ref const Json other) const { if( m_type != other.m_type ) return m_type < other.m_type ? -1 : 1; final switch(m_type){ case Type.undefined: return 0; case Type.null_: return 0; case Type.bool_: return m_bool < other.m_bool ? -1 : m_bool == other.m_bool ? 0 : 1; case Type.int_: return m_int < other.m_int ? -1 : m_int == other.m_int ? 0 : 1; case Type.float_: return m_float < other.m_float ? -1 : m_float == other.m_float ? 0 : 1; case Type.string: return m_string < other.m_string ? -1 : m_string == other.m_string ? 0 : 1; case Type.array: return m_array < other.m_array ? -1 : m_array == other.m_array ? 0 : 1; case Type.object: enforceJson(false, "JSON objects cannot be compared."); assert(false); } } alias opDollar = length; /** Returns the type id corresponding to the given D type. */ static @property Type typeId(T)() { static if( is(T == typeof(null)) ) return Type.null_; else static if( is(T == bool) ) return Type.bool_; else static if( is(T == double) ) return Type.float_; else static if( is(T == float) ) return Type.float_; else static if( is(T : long) ) return Type.int_; else static if( is(T == string) ) return Type.string; else static if( is(T == Json[]) ) return Type.array; else static if( is(T == Json[string]) ) return Type.object; else static assert(false, "Unsupported JSON type '"~T.stringof~"'. Only bool, long, double, string, Json[] and Json[string] are allowed."); } /** Returns the JSON object as a string. For large JSON values use writeJsonString instead as this function will store the whole string in memory, whereas writeJsonString writes it out bit for bit. See_Also: writeJsonString, toPrettyString */ string toString() const { auto ret = appender!string(); writeJsonString(ret, this); return ret.data; } /** Returns the JSON object as a "pretty" string. --- auto json = Json(["foo": Json("bar")]); writeln(json.toPrettyString()); // output: // { // "foo": "bar" // } --- Params: level = Specifies the base amount of indentation for the output. Indentation is always done using tab characters. See_Also: writePrettyJsonString, toString */ string toPrettyString(int level = 0) const { auto ret = appender!string(); writePrettyJsonString(ret, this, level); return ret.data; } private void checkType(TYPES...)(string op = null) const { bool matched = false; foreach (T; TYPES) if (m_type == typeId!T) matched = true; if (matched) return; string name; version (VibeJsonFieldNames) { if (m_name.length) name = m_name ~ " of type " ~ m_type.to!string; else name = "JSON of type " ~ m_type.to!string; } else name = "JSON of type " ~ m_type.to!string; string expected; static if (TYPES.length == 1) expected = typeId!(TYPES[0]).to!string; else { foreach (T; TYPES) { if (expected.length > 0) expected ~= ", "; expected ~= typeId!T.to!string; } } enforceJson(op.length > 0, format("Got %s, expected %s.", name, expected), m_fileName, line); enforceJson(false, format("Got %s, expected %s for %s.", name, expected, op), m_fileName, line); } /*invariant() { assert(m_type >= Type.Undefined && m_type <= Type.Object); }*/ } /******************************************************************************/ /* public functions */ /******************************************************************************/ /** Parses the given range as a JSON string and returns the corresponding Json object. The range is shrunk during parsing, leaving any remaining text that is not part of the JSON contents. Throws a JSONException if any parsing error occurred. */ Json parseJson(R)(ref R range, int* line = null, string filename = null) if( is(R == string) ) { import std.string : startsWith; Json ret; enforceJson(!range.empty, "JSON string is empty.", filename, 0); skipWhitespace(range, line); version(JsonLineNumbers) { import dub.internal.vibecompat.core.log; int curline = line ? *line : 0; } switch( range.front ){ case 'f': enforceJson(range[1 .. $].startsWith("alse"), "Expected 'false', got '"~range[0 .. min(5, $)]~"'.", filename, line); range.popFrontN(5); ret = false; break; case 'n': enforceJson(range[1 .. $].startsWith("ull"), "Expected 'null', got '"~range[0 .. min(4, $)]~"'.", filename, line); range.popFrontN(4); ret = null; break; case 't': enforceJson(range[1 .. $].startsWith("rue"), "Expected 'true', got '"~range[0 .. min(4, $)]~"'.", filename, line); range.popFrontN(4); ret = true; break; case '0': .. case '9': case '-': bool is_float; auto num = skipNumber(range, is_float, filename, line); if( is_float ) ret = to!double(num); else ret = to!long(num); break; case '\"': ret = skipJsonString(range, filename, line); break; case '[': Json[] arr; range.popFront(); while (true) { skipWhitespace(range, line); enforceJson(!range.empty, "Missing ']' before EOF.", filename, line); if(range.front == ']') break; arr ~= parseJson(range, line, filename); skipWhitespace(range, line); enforceJson(!range.empty, "Missing ']' before EOF.", filename, line); enforceJson(range.front == ',' || range.front == ']', format("Expected ']' or ',' - got '%s'.", range.front), filename, line); if( range.front == ']' ) break; else range.popFront(); } range.popFront(); ret = arr; break; case '{': Json[string] obj; range.popFront(); while (true) { skipWhitespace(range, line); enforceJson(!range.empty, "Missing '}' before EOF.", filename, line); if(range.front == '}') break; string key = skipJsonString(range, filename, line); skipWhitespace(range, line); enforceJson(range.startsWith(":"), "Expected ':' for key '" ~ key ~ "'", filename, line); range.popFront(); skipWhitespace(range, line); Json itm = parseJson(range, line, filename); obj[key] = itm; skipWhitespace(range, line); enforceJson(!range.empty, "Missing '}' before EOF.", filename, line); enforceJson(range.front == ',' || range.front == '}', format("Expected '}' or ',' - got '%s'.", range.front), filename, line); if (range.front == '}') break; else range.popFront(); } range.popFront(); ret = obj; break; default: enforceJson(false, format("Expected valid JSON token, got '%s'.", range[0 .. min(12, $)]), filename, line); assert(false); } assert(ret.type != Json.Type.undefined); version(JsonLineNumbers) ret.line = curline; ret.m_fileName = filename; return ret; } /** Parses the given JSON string and returns the corresponding Json object. Throws a JSONException if any parsing error occurs. */ Json parseJsonString(string str, string filename = null) { import std.string : strip; auto strcopy = str; int line = 0; auto ret = parseJson(strcopy, &line, filename); enforceJson(strcopy.strip().length == 0, "Expected end of string after JSON value.", filename, line); return ret; } unittest { assert(parseJsonString("null") == Json(null)); assert(parseJsonString("true") == Json(true)); assert(parseJsonString("false") == Json(false)); assert(parseJsonString("1") == Json(1)); assert(parseJsonString("2.0") == Json(2.0)); assert(parseJsonString("\"test\"") == Json("test")); assert(parseJsonString("[1, 2, 3]") == Json([Json(1), Json(2), Json(3)])); assert(parseJsonString("{\"a\": 1}") == Json(["a": Json(1)])); assert(parseJsonString(`"\\\/\b\f\n\r\t\u1234"`).get!string == "\\/\b\f\n\r\t\u1234"); auto json = parseJsonString(`{"hey": "This is @à test éhééhhéhéé !%/??*&?\ud83d\udcec"}`); assert(json.toPrettyString() == parseJsonString(json.toPrettyString()).toPrettyString()); } unittest { import std.string : endsWith; try parseJsonString(`{"a": 1`); catch (Exception e) assert(e.msg.endsWith("Missing '}' before EOF.")); try parseJsonString(`{"a": 1 x`); catch (Exception e) assert(e.msg.endsWith("Expected '}' or ',' - got 'x'.")); try parseJsonString(`[1`); catch (Exception e) assert(e.msg.endsWith("Missing ']' before EOF.")); try parseJsonString(`[1 x`); catch (Exception e) assert(e.msg.endsWith("Expected ']' or ',' - got 'x'.")); } /** Serializes the given value to JSON. The following types of values are supported: $(DL $(DT `Json`) $(DD Used as-is) $(DT `null`) $(DD Converted to `Json.Type.null_`) $(DT `bool`) $(DD Converted to `Json.Type.bool_`) $(DT `float`, `double`) $(DD Converted to `Json.Type.float_`) $(DT `short`, `ushort`, `int`, `uint`, `long`, `ulong`) $(DD Converted to `Json.Type.int_`) $(DT `string`) $(DD Converted to `Json.Type.string`) $(DT `T[]`) $(DD Converted to `Json.Type.array`) $(DT `T[string]`) $(DD Converted to `Json.Type.object`) $(DT `struct`) $(DD Converted to `Json.Type.object`) $(DT `class`) $(DD Converted to `Json.Type.object` or `Json.Type.null_`) ) All entries of an array or an associative array, as well as all R/W properties and all public fields of a struct/class are recursively serialized using the same rules. Fields ending with an underscore will have the last underscore stripped in the serialized output. This makes it possible to use fields with D keywords as their name by simply appending an underscore. The following methods can be used to customize the serialization of structs/classes: --- Json toJson() const; static T fromJson(Json src); string toString() const; static T fromString(string src); --- The methods will have to be defined in pairs. The first pair that is implemented by the type will be used for serialization (i.e. `toJson` overrides `toString`). See_Also: `deserializeJson`, `vibe.data.serialization` */ Json serializeToJson(T)(T value) { version (VibeOldSerialization) { return serializeToJsonOld(value); } else { return serialize!JsonSerializer(value); } } /// ditto void serializeToJson(R, T)(R destination, T value) if (isOutputRange!(R, char) || isOutputRange!(R, ubyte)) { serialize!(JsonStringSerializer!R)(value, destination); } /// ditto string serializeToJsonString(T)(T value) { auto ret = appender!string; serializeToJson(ret, value); return ret.data; } /// unittest { struct Foo { int number; string str; } Foo f; f.number = 12; f.str = "hello"; string json = serializeToJsonString(f); assert(json == `{"number":12,"str":"hello"}`); Json jsonval = serializeToJson(f); assert(jsonval.type == Json.Type.object); assert(jsonval["number"] == Json(12)); assert(jsonval["str"] == Json("hello")); } /** Serializes the given value to a pretty printed JSON string. See_also: `serializeToJson`, `vibe.data.serialization` */ void serializeToPrettyJson(R, T)(R destination, T value) if (isOutputRange!(R, char) || isOutputRange!(R, ubyte)) { serialize!(JsonStringSerializer!(R, true))(value, destination); } /// ditto string serializeToPrettyJson(T)(T value) { auto ret = appender!string; serializeToPrettyJson(ret, value); return ret.data; } /// unittest { struct Foo { int number; string str; } Foo f; f.number = 12; f.str = "hello"; string json = serializeToPrettyJson(f); assert(json == `{ "number": 12, "str": "hello" }`); } /// private Json serializeToJsonOld(T)(T value) { import vibe.internal.meta.traits; alias TU = Unqual!T; static if (is(TU == Json)) return value; else static if (is(TU == typeof(null))) return Json(null); else static if (is(TU == bool)) return Json(value); else static if (is(TU == float)) return Json(cast(double)value); else static if (is(TU == double)) return Json(value); else static if (is(TU == DateTime)) return Json(value.toISOExtString()); else static if (is(TU == SysTime)) return Json(value.toISOExtString()); else static if (is(TU == Date)) return Json(value.toISOExtString()); else static if (is(TU : long)) return Json(cast(long)value); else static if (is(TU : string)) return Json(value); else static if (isArray!T) { auto ret = new Json[value.length]; foreach (i; 0 .. value.length) ret[i] = serializeToJson(value[i]); return Json(ret); } else static if (isAssociativeArray!TU) { Json[string] ret; alias TK = KeyType!T; foreach (key, value; value) { static if(is(TK == string)) { ret[key] = serializeToJson(value); } else static if (is(TK == enum)) { ret[to!string(key)] = serializeToJson(value); } else static if (isStringSerializable!(TK)) { ret[key.toString()] = serializeToJson(value); } else static assert("AA key type %s not supported for JSON serialization."); } return Json(ret); } else static if (isJsonSerializable!TU) { return value.toJson(); } else static if (isStringSerializable!TU) { return Json(value.toString()); } else static if (is(TU == struct)) { Json[string] ret; foreach (m; __traits(allMembers, T)) { static if (isRWField!(TU, m)) { auto mv = __traits(getMember, value, m); ret[underscoreStrip(m)] = serializeToJson(mv); } } return Json(ret); } else static if(is(TU == class)) { if (value is null) return Json(null); Json[string] ret; foreach (m; __traits(allMembers, T)) { static if (isRWField!(TU, m)) { auto mv = __traits(getMember, value, m); ret[underscoreStrip(m)] = serializeToJson(mv); } } return Json(ret); } else static if (isPointer!TU) { if (value is null) return Json(null); return serializeToJson(*value); } else { static assert(false, "Unsupported type '"~T.stringof~"' for JSON serialization."); } } /** Deserializes a JSON value into the destination variable. The same types as for `serializeToJson()` are supported and handled inversely. See_Also: `serializeToJson`, `serializeToJsonString`, `vibe.data.serialization` */ void deserializeJson(T)(ref T dst, Json src) { dst = deserializeJson!T(src); } /// ditto T deserializeJson(T)(Json src) { version (VibeOldSerialization) { return deserializeJsonOld!T(src); } else { return deserialize!(JsonSerializer, T)(src); } } /// ditto T deserializeJson(T, R)(R input) if (isInputRange!R && !is(R == Json)) { return deserialize!(JsonStringSerializer!R, T)(input); } /// private T deserializeJsonOld(T)(Json src) { import vibe.internal.meta.traits; static if( is(T == struct) || isSomeString!T || isIntegral!T || isFloatingPoint!T ) if( src.type == Json.Type.null_ ) return T.init; static if (is(T == Json)) return src; else static if (is(T == typeof(null))) { return null; } else static if (is(T == bool)) return src.get!bool; else static if (is(T == float)) return src.to!float; // since doubles are frequently serialized without else static if (is(T == double)) return src.to!double; // a decimal point, we allow conversions here else static if (is(T == DateTime)) return DateTime.fromISOExtString(src.get!string); else static if (is(T == SysTime)) return SysTime.fromISOExtString(src.get!string); else static if (is(T == Date)) return Date.fromISOExtString(src.get!string); else static if (is(T : long)) return cast(T)src.get!long; else static if (is(T : string)) return cast(T)src.get!string; else static if (isArray!T) { alias TV = typeof(T.init[0]) ; auto dst = new Unqual!TV[src.length]; foreach (size_t i, v; src) dst[i] = deserializeJson!(Unqual!TV)(v); return cast(T)dst; } else static if( isAssociativeArray!T ) { alias TV = typeof(T.init.values[0]) ; alias TK = KeyType!T; Unqual!TV[TK] dst; foreach (string key, value; src) { static if (is(TK == string)) { dst[key] = deserializeJson!(Unqual!TV)(value); } else static if (is(TK == enum)) { dst[to!(TK)(key)] = deserializeJson!(Unqual!TV)(value); } else static if (isStringSerializable!TK) { auto dsk = TK.fromString(key); dst[dsk] = deserializeJson!(Unqual!TV)(value); } else static assert("AA key type %s not supported for JSON serialization."); } return dst; } else static if (isJsonSerializable!T) { return T.fromJson(src); } else static if (isStringSerializable!T) { return T.fromString(src.get!string); } else static if (is(T == struct)) { T dst; foreach (m; __traits(allMembers, T)) { static if (isRWPlainField!(T, m) || isRWField!(T, m)) { alias TM = typeof(__traits(getMember, dst, m)) ; __traits(getMember, dst, m) = deserializeJson!TM(src[underscoreStrip(m)]); } } return dst; } else static if (is(T == class)) { if (src.type == Json.Type.null_) return null; auto dst = new T; foreach (m; __traits(allMembers, T)) { static if (isRWPlainField!(T, m) || isRWField!(T, m)) { alias TM = typeof(__traits(getMember, dst, m)) ; __traits(getMember, dst, m) = deserializeJson!TM(src[underscoreStrip(m)]); } } return dst; } else static if (isPointer!T) { if (src.type == Json.Type.null_) return null; alias TD = typeof(*T.init) ; dst = new TD; *dst = deserializeJson!TD(src); return dst; } else { static assert(false, "Unsupported type '"~T.stringof~"' for JSON serialization."); } } /// unittest { struct Foo { int number; string str; } Foo f = deserializeJson!Foo(`{"number": 12, "str": "hello"}`); assert(f.number == 12); assert(f.str == "hello"); } unittest { import std.stdio; enum Foo : string { k = "test" } enum Boo : int { l = 5 } static struct S { float a; double b; bool c; int d; string e; byte f; ubyte g; long h; ulong i; float[] j; Foo k; Boo l; } immutable S t = {1.5, -3.0, true, int.min, "Test", -128, 255, long.min, ulong.max, [1.1, 1.2, 1.3], Foo.k, Boo.l}; S u; deserializeJson(u, serializeToJson(t)); assert(t.a == u.a); assert(t.b == u.b); assert(t.c == u.c); assert(t.d == u.d); assert(t.e == u.e); assert(t.f == u.f); assert(t.g == u.g); assert(t.h == u.h); assert(t.i == u.i); assert(t.j == u.j); assert(t.k == u.k); assert(t.l == u.l); } unittest { assert(uint.max == serializeToJson(uint.max).deserializeJson!uint); assert(ulong.max == serializeToJson(ulong.max).deserializeJson!ulong); } unittest { static struct A { int value; static A fromJson(Json val) { return A(val.get!int); } Json toJson() const { return Json(value); } } static struct C { int value; static C fromString(string val) { return C(val.to!int); } string toString() const { return value.to!string; } } static struct D { int value; } assert(serializeToJson(const A(123)) == Json(123)); assert(serializeToJson(A(123)) == Json(123)); assert(serializeToJson(const C(123)) == Json("123")); assert(serializeToJson(C(123)) == Json("123")); assert(serializeToJson(const D(123)) == serializeToJson(["value": 123])); assert(serializeToJson(D(123)) == serializeToJson(["value": 123])); } unittest { auto d = Date(2001,1,1); deserializeJson(d, serializeToJson(Date.init)); assert(d == Date.init); deserializeJson(d, serializeToJson(Date(2001,1,1))); assert(d == Date(2001,1,1)); struct S { immutable(int)[] x; } S s; deserializeJson(s, serializeToJson(S([1,2,3]))); assert(s == S([1,2,3])); struct T { @optional S s; @optional int i; @optional float f_; // underscore strip feature @optional double d; @optional string str; } auto t = T(S([1,2,3])); deserializeJson(t, parseJsonString(`{ "s" : null, "i" : null, "f" : null, "d" : null, "str" : null }`)); assert(text(t) == text(T())); } unittest { static class C { int a; private int _b; @property int b() const { return _b; } @property void b(int v) { _b = v; } @property int test() const { return 10; } void test2() {} } C c = new C; c.a = 1; c.b = 2; C d; deserializeJson(d, serializeToJson(c)); assert(c.a == d.a); assert(c.b == d.b); } unittest { static struct C { int value; static C fromString(string val) { return C(val.to!int); } string toString() const { return value.to!string; } } enum Color { Red, Green, Blue } { static class T { string[Color] enumIndexedMap; string[C] stringableIndexedMap; this() { enumIndexedMap = [ Color.Red : "magenta", Color.Blue : "deep blue" ]; stringableIndexedMap = [ C(42) : "forty-two" ]; } } T original = new T; original.enumIndexedMap[Color.Green] = "olive"; T other; deserializeJson(other, serializeToJson(original)); assert(serializeToJson(other) == serializeToJson(original)); } { static struct S { string[Color] enumIndexedMap; string[C] stringableIndexedMap; } S *original = new S; original.enumIndexedMap = [ Color.Red : "magenta", Color.Blue : "deep blue" ]; original.enumIndexedMap[Color.Green] = "olive"; original.stringableIndexedMap = [ C(42) : "forty-two" ]; S other; deserializeJson(other, serializeToJson(original)); assert(serializeToJson(other) == serializeToJson(original)); } } unittest { import std.typecons : Nullable; struct S { Nullable!int a, b; } S s; s.a = 2; auto j = serializeToJson(s); assert(j["a"].type == Json.Type.int_); assert(j["b"].type == Json.Type.null_); auto t = deserializeJson!S(j); assert(!t.a.isNull() && t.a == 2); assert(t.b.isNull()); } unittest { // #840 int[2][2] nestedArray = 1; assert(nestedArray.serializeToJson.deserializeJson!(typeof(nestedArray)) == nestedArray); } /** Serializer for a plain Json representation. See_Also: vibe.data.serialization.serialize, vibe.data.serialization.deserialize, serializeToJson, deserializeJson */ struct JsonSerializer { template isJsonBasicType(T) { enum isJsonBasicType = isNumeric!T || isBoolean!T || is(T == string) || is(T == typeof(null)) || isJsonSerializable!T; } template isSupportedValueType(T) { enum isSupportedValueType = isJsonBasicType!T || is(T == Json); } private { Json m_current; Json[] m_compositeStack; } this(Json data) { m_current = data; } @disable this(this); // // serialization // Json getSerializedResult() { return m_current; } void beginWriteDictionary(T)() { m_compositeStack ~= Json.emptyObject; } void endWriteDictionary(T)() { m_current = m_compositeStack[$-1]; m_compositeStack.length--; } void beginWriteDictionaryEntry(T)(string name) {} void endWriteDictionaryEntry(T)(string name) { m_compositeStack[$-1][name] = m_current; } void beginWriteArray(T)(size_t) { m_compositeStack ~= Json.emptyArray; } void endWriteArray(T)() { m_current = m_compositeStack[$-1]; m_compositeStack.length--; } void beginWriteArrayEntry(T)(size_t) {} void endWriteArrayEntry(T)(size_t) { m_compositeStack[$-1].appendArrayElement(m_current); } void writeValue(T)(T value) { static if (is(T == Json)) m_current = value; else static if (isJsonSerializable!T) m_current = value.toJson(); else m_current = Json(value); } void writeValue(T)(in Json value) if (is(T == Json)) { m_current = value.clone; } // // deserialization // void readDictionary(T)(scope void delegate(string) field_handler) { enforceJson(m_current.type == Json.Type.object, "Expected JSON object, got "~m_current.type.to!string); auto old = m_current; foreach (string key, value; m_current) { m_current = value; field_handler(key); } m_current = old; } void readArray(T)(scope void delegate(size_t) size_callback, scope void delegate() entry_callback) { enforceJson(m_current.type == Json.Type.array, "Expected JSON array, got "~m_current.type.to!string); auto old = m_current; size_callback(m_current.length); foreach (ent; old) { m_current = ent; entry_callback(); } m_current = old; } T readValue(T)() { static if (is(T == Json)) return m_current; else static if (isJsonSerializable!T) return T.fromJson(m_current); else static if (is(T == float) || is(T == double)) { if (m_current.type == Json.Type.undefined) return T.nan; return m_current.type == Json.Type.float_ ? cast(T)m_current.get!double : cast(T)m_current.get!long; } else { return m_current.get!T(); } } bool tryReadNull() { return m_current.type == Json.Type.null_; } } /** Serializer for a range based plain JSON string representation. See_Also: vibe.data.serialization.serialize, vibe.data.serialization.deserialize, serializeToJson, deserializeJson */ struct JsonStringSerializer(R, bool pretty = false) if (isInputRange!R || isOutputRange!(R, char)) { private { R m_range; size_t m_level = 0; } template isJsonBasicType(T) { enum isJsonBasicType = isNumeric!T || isBoolean!T || is(T == string) || is(T == typeof(null)) || isJsonSerializable!T; } template isSupportedValueType(T) { enum isSupportedValueType = isJsonBasicType!T || is(T == Json); } this(R range) { m_range = range; } @disable this(this); // // serialization // static if (isOutputRange!(R, char)) { private { bool m_firstInComposite; } void getSerializedResult() {} void beginWriteDictionary(T)() { startComposite(); m_range.put('{'); } void endWriteDictionary(T)() { endComposite(); m_range.put("}"); } void beginWriteDictionaryEntry(T)(string name) { startCompositeEntry(); m_range.put('"'); m_range.jsonEscape(name); static if (pretty) m_range.put(`": `); else m_range.put(`":`); } void endWriteDictionaryEntry(T)(string name) {} void beginWriteArray(T)(size_t) { startComposite(); m_range.put('['); } void endWriteArray(T)() { endComposite(); m_range.put(']'); } void beginWriteArrayEntry(T)(size_t) { startCompositeEntry(); } void endWriteArrayEntry(T)(size_t) {} void writeValue(T)(in T value) { static if (is(T == typeof(null))) m_range.put("null"); else static if (is(T == bool)) m_range.put(value ? "true" : "false"); else static if (is(T : long)) m_range.formattedWrite("%s", value); else static if (is(T : real)) m_range.formattedWrite("%.16g", value); else static if (is(T == string)) { m_range.put('"'); m_range.jsonEscape(value); m_range.put('"'); } else static if (is(T == Json)) m_range.writeJsonString(value); else static if (isJsonSerializable!T) m_range.writeJsonString!(R, pretty)(value.toJson(), m_level); else static assert(false, "Unsupported type: " ~ T.stringof); } private void startComposite() { static if (pretty) m_level++; m_firstInComposite = true; } private void startCompositeEntry() { if (!m_firstInComposite) { m_range.put(','); } else { m_firstInComposite = false; } static if (pretty) indent(); } private void endComposite() { static if (pretty) { m_level--; if (!m_firstInComposite) indent(); } m_firstInComposite = false; } private void indent() { m_range.put('\n'); foreach (i; 0 .. m_level) m_range.put('\t'); } } // // deserialization // static if (isInputRange!(R)) { private { int m_line = 0; } void readDictionary(T)(scope void delegate(string) entry_callback) { m_range.skipWhitespace(&m_line); enforceJson(!m_range.empty && m_range.front == '{', "Expecting object."); m_range.popFront(); bool first = true; while(true) { m_range.skipWhitespace(&m_line); enforceJson(!m_range.empty, "Missing '}'."); if (m_range.front == '}') { m_range.popFront(); break; } else if (!first) { enforceJson(m_range.front == ',', "Expecting ',' or '}', not '"~m_range.front.to!string~"'."); m_range.popFront(); m_range.skipWhitespace(&m_line); } else first = false; auto name = m_range.skipJsonString(null, &m_line); m_range.skipWhitespace(&m_line); enforceJson(!m_range.empty && m_range.front == ':', "Expecting ':', not '"~m_range.front.to!string~"'."); m_range.popFront(); entry_callback(name); } } void readArray(T)(scope void delegate(size_t) size_callback, scope void delegate() entry_callback) { m_range.skipWhitespace(&m_line); enforceJson(!m_range.empty && m_range.front == '[', "Expecting array."); m_range.popFront(); bool first = true; while(true) { m_range.skipWhitespace(&m_line); enforceJson(!m_range.empty, "Missing ']'."); if (m_range.front == ']') { m_range.popFront(); break; } else if (!first) { enforceJson(m_range.front == ',', "Expecting ',' or ']'."); m_range.popFront(); } else first = false; entry_callback(); } } T readValue(T)() { m_range.skipWhitespace(&m_line); static if (is(T == typeof(null))) { enforceJson(m_range.take(4).equal("null"), "Expecting 'null'."); return null; } else static if (is(T == bool)) { bool ret = m_range.front == 't'; string expected = ret ? "true" : "false"; foreach (ch; expected) { enforceJson(m_range.front == ch, "Expecting 'true' or 'false'."); m_range.popFront(); } return ret; } else static if (is(T : long)) { bool is_float; auto num = m_range.skipNumber(is_float, null, &m_line); enforceJson(!is_float, "Expecting integer number."); return to!T(num); } else static if (is(T : real)) { bool is_float; auto num = m_range.skipNumber(is_float); return to!T(num); } else static if (is(T == string)) return m_range.skipJsonString(null, &m_line); else static if (is(T == Json)) return m_range.parseJson(&m_line); else static if (isJsonSerializable!T) return T.fromJson(m_range.parseJson(&m_line)); else static assert(false, "Unsupported type: " ~ T.stringof); } bool tryReadNull() { m_range.skipWhitespace(&m_line); if (m_range.front != 'n') return false; foreach (ch; "null") { enforceJson(m_range.front == ch, "Expecting 'null'."); m_range.popFront(); } assert(m_range.empty || m_range.front != 'l'); return true; } } } /** Writes the given JSON object as a JSON string into the destination range. This function will convert the given JSON value to a string without adding any white space between tokens (no newlines, no indentation and no padding). The output size is thus minimized, at the cost of bad human readability. Params: dst = References the string output range to which the result is written. json = Specifies the JSON value that is to be stringified. See_Also: Json.toString, writePrettyJsonString */ void writeJsonString(R, bool pretty = false)(ref R dst, in Json json, size_t level = 0) // if( isOutputRange!R && is(ElementEncodingType!R == char) ) { final switch( json.type ){ case Json.Type.undefined: dst.put("undefined"); break; case Json.Type.null_: dst.put("null"); break; case Json.Type.bool_: dst.put(cast(bool)json ? "true" : "false"); break; case Json.Type.int_: formattedWrite(dst, "%d", json.get!long); break; case Json.Type.float_: auto d = json.get!double; if (d != d) dst.put("undefined"); // JSON has no NaN value so set null else formattedWrite(dst, "%.16g", json.get!double); break; case Json.Type.string: dst.put('\"'); jsonEscape(dst, cast(string)json); dst.put('\"'); break; case Json.Type.array: dst.put('['); bool first = true; foreach (ref const Json e; json) { if( !first ) dst.put(","); first = false; static if (pretty) { dst.put('\n'); foreach (tab; 0 .. level+1) dst.put('\t'); } if (e.type == Json.Type.undefined) dst.put("null"); else writeJsonString!(R, pretty)(dst, e, level+1); } static if (pretty) { if (json.length > 0) { dst.put('\n'); foreach (tab; 0 .. level) dst.put('\t'); } } dst.put(']'); break; case Json.Type.object: dst.put('{'); bool first = true; static if (pretty) { import std.algorithm.sorting : sort; string[] keyOrder; foreach (string key, ref const Json e; json) keyOrder ~= key; keyOrder.sort(); foreach( key; keyOrder ){ if( json[key].type == Json.Type.undefined ) continue; if( !first ) dst.put(','); first = false; dst.put('\n'); foreach (tab; 0 .. level+1) dst.put('\t'); dst.put('\"'); jsonEscape(dst, key); dst.put(pretty ? `": ` : `":`); writeJsonString!(R, pretty)(dst, json[key], level+1); } if (json.length > 0) { dst.put('\n'); foreach (tab; 0 .. level) dst.put('\t'); } } else { foreach( string k, ref const Json e; json ){ if( e.type == Json.Type.undefined ) continue; if( !first ) dst.put(','); first = false; dst.put('\"'); jsonEscape(dst, k); dst.put(pretty ? `": ` : `":`); writeJsonString!(R, pretty)(dst, e, level+1); } } dst.put('}'); break; } } unittest { auto a = Json.emptyObject; a["a"] = Json.emptyArray; a["b"] = Json.emptyArray; a["b"] ~= Json(1); a["b"] ~= Json.emptyObject; assert(a.toString() == `{"a":[],"b":[1,{}]}` || a.toString == `{"b":[1,{}],"a":[]}`); assert(a.toPrettyString() == `{ "a": [], "b": [ 1, {} ] }`); } unittest { // #735 auto a = Json.emptyArray; a ~= "a"; a ~= Json(); a ~= "b"; a ~= null; a ~= "c"; assert(a.toString() == `["a",null,"b",null,"c"]`); } unittest { auto a = Json.emptyArray; a ~= Json(1); a ~= Json(2); a ~= Json(3); a ~= Json(4); a ~= Json(5); auto b = Json(a[0..a.length]); assert(a == b); auto c = Json(a[0..$]); assert(a == c); assert(b == c); auto d = [Json(1),Json(2),Json(3)]; assert(d == a[0..a.length-2]); assert(d == a[0..$-2]); } unittest { auto j = Json(double.init); assert(j.toString == "undefined"); // A double nan should serialize to undefined j = 17.04f; assert(j.toString == "17.04"); // A proper double should serialize correctly double d; deserializeJson(d, Json.undefined); // Json.undefined should deserialize to nan assert(d != d); } /** Writes the given JSON object as a prettified JSON string into the destination range. The output will contain newlines and indents to make the output human readable. Params: dst = References the string output range to which the result is written. json = Specifies the JSON value that is to be stringified. level = Specifies the base amount of indentation for the output. Indentation is always done using tab characters. See_Also: Json.toPrettyString, writeJsonString */ void writePrettyJsonString(R)(ref R dst, in Json json, int level = 0) // if( isOutputRange!R && is(ElementEncodingType!R == char) ) { writeJsonString!(R, true)(dst, json, level); } /** Helper function that escapes all Unicode characters in a JSON string. */ string convertJsonToASCII(string json) { auto ret = appender!string; jsonEscape!true(ret, json); return ret.data; } /// private private void jsonEscape(bool escape_unicode = false, R)(ref R dst, string s) { for (size_t pos = 0; pos < s.length; pos++) { immutable(char) ch = s[pos]; switch (ch) { default: static if (escape_unicode) { if (ch > 0x20 && ch < 0x80) dst.put(ch); else { import std.utf : decode; char[13] buf; int len; dchar codepoint = decode(s, pos); import core.stdc.stdio : sprintf; /* codepoint is in BMP */ if(codepoint < 0x10000) { sprintf(&buf[0], "\\u%04X", codepoint); len = 6; } /* not in BMP -> construct a UTF-16 surrogate pair */ else { int first, last; codepoint -= 0x10000; first = 0xD800 | ((codepoint & 0xffc00) >> 10); last = 0xDC00 | (codepoint & 0x003ff); sprintf(&buf[0], "\\u%04X\\u%04X", first, last); len = 12; } pos -= 1; foreach (i; 0 .. len) dst.put(buf[i]); } } else { if (ch < 0x20) dst.formattedWrite("\\u%04X", ch); else dst.put(ch); } break; case '\\': dst.put("\\\\"); break; case '\r': dst.put("\\r"); break; case '\n': dst.put("\\n"); break; case '\t': dst.put("\\t"); break; case '\"': dst.put("\\\""); break; } } } /// private private string jsonUnescape(R)(ref R range, string filename, int* line) { auto ret = appender!string(); while(!range.empty){ auto ch = range.front; switch( ch ){ case '"': return ret.data; case '\\': range.popFront(); enforceJson(!range.empty, "Unterminated string escape sequence.", filename, line); switch(range.front){ default: enforceJson(false, "Invalid string escape sequence.", filename, line); break; case '"': ret.put('\"'); range.popFront(); break; case '\\': ret.put('\\'); range.popFront(); break; case '/': ret.put('/'); range.popFront(); break; case 'b': ret.put('\b'); range.popFront(); break; case 'f': ret.put('\f'); range.popFront(); break; case 'n': ret.put('\n'); range.popFront(); break; case 'r': ret.put('\r'); range.popFront(); break; case 't': ret.put('\t'); range.popFront(); break; case 'u': dchar decode_unicode_escape() { enforceJson(range.front == 'u'); range.popFront(); dchar uch = 0; foreach( i; 0 .. 4 ){ uch *= 16; enforceJson(!range.empty, "Unicode sequence must be '\\uXXXX'.", filename, line); auto dc = range.front; range.popFront(); if( dc >= '0' && dc <= '9' ) uch += dc - '0'; else if( dc >= 'a' && dc <= 'f' ) uch += dc - 'a' + 10; else if( dc >= 'A' && dc <= 'F' ) uch += dc - 'A' + 10; else enforceJson(false, "Unicode sequence must be '\\uXXXX'.", filename, line); } return uch; } auto uch = decode_unicode_escape(); if(0xD800 <= uch && uch <= 0xDBFF) { /* surrogate pair */ range.popFront(); // backslash '\' auto uch2 = decode_unicode_escape(); enforceJson(0xDC00 <= uch2 && uch2 <= 0xDFFF, "invalid Unicode", filename, line); { /* valid second surrogate */ uch = ((uch - 0xD800) << 10) + (uch2 - 0xDC00) + 0x10000; } } ret.put(uch); break; } break; default: ret.put(ch); range.popFront(); break; } } return ret.data; } /// private private string skipNumber(R)(ref R s, out bool is_float, string filename, int* line) { // TODO: make this work with input ranges size_t idx = 0; is_float = false; if (s[idx] == '-') idx++; if (s[idx] == '0') idx++; else { enforceJson(isDigit(s[idx++]), "Digit expected at beginning of number.", filename, line); while( idx < s.length && isDigit(s[idx]) ) idx++; } if( idx < s.length && s[idx] == '.' ){ idx++; is_float = true; while( idx < s.length && isDigit(s[idx]) ) idx++; } if( idx < s.length && (s[idx] == 'e' || s[idx] == 'E') ){ idx++; is_float = true; if( idx < s.length && (s[idx] == '+' || s[idx] == '-') ) idx++; enforceJson( idx < s.length && isDigit(s[idx]), "Expected exponent." ~ s[0 .. idx], filename, line); idx++; while( idx < s.length && isDigit(s[idx]) ) idx++; } string ret = s[0 .. idx]; s = s[idx .. $]; return ret; } /// private private string skipJsonString(R)(ref R s, string filename, int* line) { // TODO: count or disallow any newlines inside of the string enforceJson(!s.empty && s.front == '"', "Expected '\"' to start string.", filename, line); s.popFront(); string ret = jsonUnescape(s, filename, line); enforceJson(!s.empty && s.front == '"', "Expected '\"' to terminate string.", filename, line); s.popFront(); return ret; } /// private private void skipWhitespace(R)(ref R s, int* line = null) { while (!s.empty) { switch (s.front) { default: return; case ' ', '\t': s.popFront(); break; case '\n': s.popFront(); if (!s.empty && s.front == '\r') s.popFront(); if (line) (*line)++; break; case '\r': s.popFront(); if (!s.empty && s.front == '\n') s.popFront(); if (line) (*line)++; break; } } } private bool isDigit(dchar ch) { return ch >= '0' && ch <= '9'; } private string underscoreStrip(string field_name) { if( field_name.length < 1 || field_name[$-1] != '_' ) return field_name; else return field_name[0 .. $-1]; } /// private package template isJsonSerializable(T) { enum isJsonSerializable = is(typeof(T.init.toJson()) == Json) && is(typeof(T.fromJson(Json())) == T); } private void enforceJson(string file = __FILE__, size_t line = __LINE__)(bool cond, lazy string message = "JSON exception") { static if (__VERSION__ >= 2079) enforce!JSONException(cond, message, file, line); else enforceEx!JSONException(cond, message, file, line); } private void enforceJson(string file = __FILE__, size_t line = __LINE__)(bool cond, lazy string message, string err_file, int err_line) { auto errmsg() { return format("%s(%s): Error: %s", err_file, err_line+1, message); } static if (__VERSION__ >= 2079) enforce!JSONException(cond, errmsg, file, line); else enforceEx!JSONException(cond, errmsg, file, line); } private void enforceJson(string file = __FILE__, size_t line = __LINE__)(bool cond, lazy string message, string err_file, int* err_line) { enforceJson!(file, line)(cond, message, err_file, err_line ? *err_line : -1); } dub-1.19.0/source/dub/internal/vibecompat/data/serialization.d000066400000000000000000001233271360435400500243360ustar00rootroot00000000000000/** Generic serialization framework. This module provides general means for implementing (de-)serialization with a standardized behavior. Supported_types: The following rules are applied in order when serializing or deserializing a certain type: $(OL $(LI An `enum` type is serialized as its raw value, except if `@byName` is used, in which case the name of the enum value is serialized.) $(LI Any type that is specifically supported by the serializer is directly serialized. For example, the BSON serializer supports `BsonObjectID` directly.) $(LI Arrays and tuples (`std.typecons.Tuple`) are serialized using the array serialization functions where each element is serialized again according to these rules.) $(LI Associative arrays are serialized similar to arrays. The key type of the AA must satisfy the `isStringSerializable` trait and will always be serialized as a string.) $(LI Any `Nullable!T` will be serialized as either `null`, or as the contained value (subject to these rules again).) $(LI Any `BitFlags!T` value will be serialized as `T[]`) $(LI Types satisfying the `isPolicySerializable` trait for the supplied `Policy` will be serialized as the value returned by the policy `toRepresentation` function (again subject to these rules).) $(LI Types satisfying the `isCustomSerializable` trait will be serialized as the value returned by their `toRepresentation` method (again subject to these rules).) $(LI Types satisfying the `isISOExtStringSerializable` trait will be serialized as a string, as returned by their `toISOExtString` method. This causes types such as `SysTime` to be serialized as strings.) $(LI Types satisfying the `isStringSerializable` trait will be serialized as a string, as returned by their `toString` method.) $(LI Struct and class types by default will be serialized as associative arrays, where the key is the name of the corresponding field (can be overridden using the `@name` attribute). If the struct/class is annotated with `@asArray`, it will instead be serialized as a flat array of values in the order of declaration. Null class references will be serialized as `null`.) $(LI Pointer types will be serialized as either `null`, or as the value they point to.) $(LI Built-in integers and floating point values, as well as boolean values will be converted to strings, if the serializer doesn't support them directly.) ) Note that no aliasing detection is performed, so that pointers, class references and arrays referencing the same memory will be serialized as multiple copies. When in turn deserializing the data, they will also end up as separate copies in memory. Serializer_implementation: Serializers are implemented in terms of a struct with template methods that get called by the serialization framework: --- struct ExampleSerializer { enum isSupportedValueType(T) = is(T == string) || is(T == typeof(null)); // serialization auto getSerializedResult(); void beginWriteDictionary(T)(); void endWriteDictionary(T)(); void beginWriteDictionaryEntry(T)(string name); void endWriteDictionaryEntry(T)(string name); void beginWriteArray(T)(size_t length); void endWriteArray(T)(); void beginWriteArrayEntry(T)(size_t index); void endWriteArrayEntry(T)(size_t index); void writeValue(T)(T value); // deserialization void readDictionary(T)(scope void delegate(string) entry_callback); void readArray(T)(scope void delegate(size_t) size_callback, scope void delegate() entry_callback); T readValue(T)(); bool tryReadNull(); } --- Copyright: © 2013-2014 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.internal.vibecompat.data.serialization; version (Have_vibe_d_data) public import vibe.data.serialization; else: import dub.internal.vibecompat.data.utils; import std.array : Appender, appender; import std.conv : to; import std.exception : enforce; import std.traits; import std.typetuple; /** Serializes a value with the given serializer. The serializer must have a value result for the first form to work. Otherwise, use the range based form. See_Also: `vibe.data.json.JsonSerializer`, `vibe.data.json.JsonStringSerializer`, `vibe.data.bson.BsonSerializer` */ auto serialize(Serializer, T, ARGS...)(T value, ARGS args) { auto serializer = Serializer(args); serialize(serializer, value); return serializer.getSerializedResult(); } /// ditto void serialize(Serializer, T)(ref Serializer serializer, T value) { serializeImpl!(Serializer, DefaultPolicy, T)(serializer, value); } /** Note that there is a convenience function `vibe.data.json.serializeToJson` that can be used instead of manually invoking `serialize`. */ unittest { import dub.internal.vibecompat.data.json; struct Test { int value; string text; } Test test; test.value = 12; test.text = "Hello"; Json serialized = serialize!JsonSerializer(test); assert(serialized["value"].get!int == 12); assert(serialized["text"].get!string == "Hello"); } unittest { import dub.internal.vibecompat.data.json; // Make sure that immutable(char[]) works just like string // (i.e., immutable(char)[]). immutable key = "answer"; auto ints = [key: 42]; auto serialized = serialize!JsonSerializer(ints); assert(serialized[key].get!int == 42); } /** Serializes a value with the given serializer, representing values according to `Policy` when possible. The serializer must have a value result for the first form to work. Otherwise, use the range based form. See_Also: `vibe.data.json.JsonSerializer`, `vibe.data.json.JsonStringSerializer`, `vibe.data.bson.BsonSerializer` */ auto serializeWithPolicy(Serializer, alias Policy, T, ARGS...)(T value, ARGS args) { auto serializer = Serializer(args); serializeWithPolicy!(Serializer, Policy)(serializer, value); return serializer.getSerializedResult(); } /// ditto void serializeWithPolicy(Serializer, alias Policy, T)(ref Serializer serializer, T value) { serializeImpl!(Serializer, Policy, T)(serializer, value); } /// version (unittest) { template SizePol(T) { import std.conv; import std.array; string toRepresentation(T value) { return to!string(value.x) ~ "x" ~ to!string(value.y); } T fromRepresentation(string value) { string[] fields = value.split('x'); alias fieldT = typeof(T.x); auto x = to!fieldT(fields[0]); auto y = to!fieldT(fields[1]); return T(x, y); } } } /// unittest { import dub.internal.vibecompat.data.json; static struct SizeI { int x; int y; } SizeI sizeI = SizeI(1,2); Json serializedI = serializeWithPolicy!(JsonSerializer, SizePol)(sizeI); assert(serializedI.get!string == "1x2"); static struct SizeF { float x; float y; } SizeF sizeF = SizeF(0.1f,0.2f); Json serializedF = serializeWithPolicy!(JsonSerializer, SizePol)(sizeF); assert(serializedF.get!string == "0.1x0.2"); } /** Deserializes and returns a serialized value. serialized_data can be either an input range or a value containing the serialized data, depending on the type of serializer used. See_Also: `vibe.data.json.JsonSerializer`, `vibe.data.json.JsonStringSerializer`, `vibe.data.bson.BsonSerializer` */ T deserialize(Serializer, T, ARGS...)(ARGS args) { auto deserializer = Serializer(args); return deserializeImpl!(T, DefaultPolicy, Serializer)(deserializer); } /** Note that there is a convenience function `vibe.data.json.deserializeJson` that can be used instead of manually invoking `deserialize`. */ unittest { import dub.internal.vibecompat.data.json; struct Test { int value; string text; } Json serialized = Json.emptyObject; serialized["value"] = 12; serialized["text"] = "Hello"; Test test = deserialize!(JsonSerializer, Test)(serialized); assert(test.value == 12); assert(test.text == "Hello"); } /** Deserializes and returns a serialized value, interpreting values according to `Policy` when possible. serialized_data can be either an input range or a value containing the serialized data, depending on the type of serializer used. See_Also: `vibe.data.json.JsonSerializer`, `vibe.data.json.JsonStringSerializer`, `vibe.data.bson.BsonSerializer` */ T deserializeWithPolicy(Serializer, alias Policy, T, ARGS...)(ARGS args) { auto deserializer = Serializer(args); return deserializeImpl!(T, Policy, Serializer)(deserializer); } /// unittest { import dub.internal.vibecompat.data.json; static struct SizeI { int x; int y; } Json serializedI = "1x2"; SizeI sizeI = deserializeWithPolicy!(JsonSerializer, SizePol, SizeI)(serializedI); assert(sizeI.x == 1); assert(sizeI.y == 2); static struct SizeF { float x; float y; } Json serializedF = "0.1x0.2"; SizeF sizeF = deserializeWithPolicy!(JsonSerializer, SizePol, SizeF)(serializedF); assert(sizeF.x == 0.1f); assert(sizeF.y == 0.2f); } private void serializeImpl(Serializer, alias Policy, T, ATTRIBUTES...)(ref Serializer serializer, T value) { import std.typecons : Nullable, Tuple, tuple; import std.typecons : BitFlags; static assert(Serializer.isSupportedValueType!string, "All serializers must support string values."); static assert(Serializer.isSupportedValueType!(typeof(null)), "All serializers must support null values."); alias TU = Unqual!T; static if (is(TU == enum)) { static if (hasAttributeL!(ByNameAttribute, ATTRIBUTES)) { serializeImpl!(Serializer, Policy, string)(serializer, value.to!string()); } else { serializeImpl!(Serializer, Policy, OriginalType!TU)(serializer, cast(OriginalType!TU)value); } } else static if (Serializer.isSupportedValueType!TU) { static if (is(TU == typeof(null))) serializer.writeValue!TU(null); else serializer.writeValue!TU(value); } else static if (/*isInstanceOf!(Tuple, TU)*/is(T == Tuple!TPS, TPS...)) { static if (TU.Types.length == 1) { serializeImpl!(Serializer, Policy, typeof(value[0]), ATTRIBUTES)(serializer, value[0]); } else { serializer.beginWriteArray!TU(value.length); foreach (i, TV; T.Types) { serializer.beginWriteArrayEntry!TV(i); serializeImpl!(Serializer, Policy, TV, ATTRIBUTES)(serializer, value[i]); serializer.endWriteArrayEntry!TV(i); } serializer.endWriteArray!TU(); } } else static if (isArray!TU) { alias TV = typeof(value[0]); serializer.beginWriteArray!TU(value.length); foreach (i, ref el; value) { serializer.beginWriteArrayEntry!TV(i); serializeImpl!(Serializer, Policy, TV, ATTRIBUTES)(serializer, el); serializer.endWriteArrayEntry!TV(i); } serializer.endWriteArray!TU(); } else static if (isAssociativeArray!TU) { alias TK = KeyType!TU; alias TV = ValueType!TU; static if (__traits(compiles, serializer.beginWriteDictionary!TU(0))) { auto nfields = value.length; serializer.beginWriteDictionary!TU(nfields); } else { serializer.beginWriteDictionary!TU(); } foreach (key, ref el; value) { string keyname; static if (is(TK : string)) keyname = key; else static if (is(TK : real) || is(TK : long) || is(TK == enum)) keyname = key.to!string; else static if (isStringSerializable!TK) keyname = key.toString(); else static assert(false, "Associative array keys must be strings, numbers, enums, or have toString/fromString methods."); serializer.beginWriteDictionaryEntry!TV(keyname); serializeImpl!(Serializer, Policy, TV, ATTRIBUTES)(serializer, el); serializer.endWriteDictionaryEntry!TV(keyname); } static if (__traits(compiles, serializer.endWriteDictionary!TU(0))) { serializer.endWriteDictionary!TU(nfields); } else { serializer.endWriteDictionary!TU(); } } else static if (/*isInstanceOf!(Nullable, TU)*/is(T == Nullable!TPS, TPS...)) { if (value.isNull()) serializeImpl!(Serializer, Policy, typeof(null))(serializer, null); else serializeImpl!(Serializer, Policy, typeof(value.get()), ATTRIBUTES)(serializer, value.get()); } else static if (is(T == BitFlags!E, E)) { size_t cnt = 0; foreach (v; EnumMembers!E) if (value & v) cnt++; serializer.beginWriteArray!(E[])(cnt); cnt = 0; foreach (v; EnumMembers!E) if (value & v) { serializer.beginWriteArrayEntry!E(cnt); serializeImpl!(Serializer, Policy, E, ATTRIBUTES)(serializer, v); serializer.endWriteArrayEntry!E(cnt); cnt++; } serializer.endWriteArray!(E[])(); } else static if (isPolicySerializable!(Policy, TU)) { alias CustomType = typeof(Policy!TU.toRepresentation(TU.init)); serializeImpl!(Serializer, Policy, CustomType, ATTRIBUTES)(serializer, Policy!TU.toRepresentation(value)); } else static if (isCustomSerializable!TU) { alias CustomType = typeof(T.init.toRepresentation()); serializeImpl!(Serializer, Policy, CustomType, ATTRIBUTES)(serializer, value.toRepresentation()); } else static if (isISOExtStringSerializable!TU) { serializer.writeValue(value.toISOExtString()); } else static if (isStringSerializable!TU) { serializer.writeValue(value.toString()); } else static if (is(TU == struct) || is(TU == class)) { static if (!hasSerializableFields!TU) pragma(msg, "Serializing composite type "~T.stringof~" which has no serializable fields"); static if (is(TU == class)) { if (value is null) { serializeImpl!(Serializer, Policy, typeof(null))(serializer, null); return; } } static if (hasAttributeL!(AsArrayAttribute, ATTRIBUTES)) { enum nfields = getExpandedFieldCount!(TU, SerializableFields!TU); serializer.beginWriteArray!TU(nfields); foreach (mname; SerializableFields!TU) { alias TMS = TypeTuple!(typeof(__traits(getMember, value, mname))); foreach (j, TM; TMS) { alias TA = TypeTuple!(__traits(getAttributes, TypeTuple!(__traits(getMember, T, mname))[j])); serializer.beginWriteArrayEntry!TM(j); serializeImpl!(Serializer, Policy, TM, TA)(serializer, tuple(__traits(getMember, value, mname))[j]); serializer.endWriteArrayEntry!TM(j); } } serializer.endWriteArray!TU(); } else { static if (__traits(compiles, serializer.beginWriteDictionary!TU(0))) { enum nfields = getExpandedFieldCount!(TU, SerializableFields!TU); serializer.beginWriteDictionary!TU(nfields); } else { serializer.beginWriteDictionary!TU(); } foreach (mname; SerializableFields!TU) { alias TM = TypeTuple!(typeof(__traits(getMember, value, mname))); static if (TM.length == 1) { alias TA = TypeTuple!(__traits(getAttributes, __traits(getMember, T, mname))); enum name = getAttribute!(TU, mname, NameAttribute)(NameAttribute(underscoreStrip(mname))).name; auto vt = __traits(getMember, value, mname); serializer.beginWriteDictionaryEntry!(typeof(vt))(name); serializeImpl!(Serializer, Policy, typeof(vt), TA)(serializer, vt); serializer.endWriteDictionaryEntry!(typeof(vt))(name); } else { alias TA = TypeTuple!(); // FIXME: support attributes for tuples somehow enum name = underscoreStrip(mname); auto vt = tuple(__traits(getMember, value, mname)); serializer.beginWriteDictionaryEntry!(typeof(vt))(name); serializeImpl!(Serializer, Policy, typeof(vt), TA)(serializer, vt); serializer.endWriteDictionaryEntry!(typeof(vt))(name); } } static if (__traits(compiles, serializer.endWriteDictionary!TU(0))) { serializer.endWriteDictionary!TU(nfields); } else { serializer.endWriteDictionary!TU(); } } } else static if (isPointer!TU) { if (value is null) { serializer.writeValue(null); return; } serializeImpl!(Serializer, Policy, PointerTarget!TU)(serializer, *value); } else static if (is(TU == bool) || is(TU : real) || is(TU : long)) { serializeImpl!(Serializer, Policy, string)(serializer, to!string(value)); } else static assert(false, "Unsupported serialization type: " ~ T.stringof); } private T deserializeImpl(T, alias Policy, Serializer, ATTRIBUTES...)(ref Serializer deserializer) { import std.typecons : Nullable; import std.typecons : BitFlags; static assert(Serializer.isSupportedValueType!string, "All serializers must support string values."); static assert(Serializer.isSupportedValueType!(typeof(null)), "All serializers must support null values."); static if (is(T == enum)) { static if (hasAttributeL!(ByNameAttribute, ATTRIBUTES)) { return deserializeImpl!(string, Policy, Serializer)(deserializer).to!T(); } else { return cast(T)deserializeImpl!(OriginalType!T, Policy, Serializer)(deserializer); } } else static if (Serializer.isSupportedValueType!T) { return deserializer.readValue!T(); } else static if (isStaticArray!T) { alias TV = typeof(T.init[0]); T ret; size_t i = 0; deserializer.readArray!T((sz) { assert(sz == 0 || sz == T.length); }, { assert(i < T.length); ret[i++] = deserializeImpl!(TV, Policy, Serializer, ATTRIBUTES)(deserializer); }); return ret; } else static if (isDynamicArray!T) { alias TV = typeof(T.init[0]); //auto ret = appender!T(); T ret; // Cannot use appender because of DMD BUG 10690/10859/11357 deserializer.readArray!T((sz) { ret.reserve(sz); }, () { ret ~= deserializeImpl!(TV, Policy, Serializer, ATTRIBUTES)(deserializer); }); return ret;//cast(T)ret.data; } else static if (isAssociativeArray!T) { alias TK = KeyType!T; alias TV = ValueType!T; T ret; deserializer.readDictionary!T((name) { TK key; static if (is(TK == string)) key = name; else static if (is(TK : real) || is(TK : long) || is(TK == enum)) key = name.to!TK; else static if (isStringSerializable!TK) key = TK.fromString(name); else static assert(false, "Associative array keys must be strings, numbers, enums, or have toString/fromString methods."); ret[key] = deserializeImpl!(TV, Policy, Serializer, ATTRIBUTES)(deserializer); }); return ret; } else static if (isInstanceOf!(Nullable, T)) { if (deserializer.tryReadNull()) return T.init; return T(deserializeImpl!(typeof(T.init.get()), Policy, Serializer, ATTRIBUTES)(deserializer)); } else static if (is(T == BitFlags!E, E)) { T ret; deserializer.readArray!(E[])((sz) {}, { ret |= deserializeImpl!(E, Policy, Serializer, ATTRIBUTES)(deserializer); }); return ret; } else static if (isPolicySerializable!(Policy, T)) { alias CustomType = typeof(Policy!T.toRepresentation(T.init)); return Policy!T.fromRepresentation(deserializeImpl!(CustomType, Policy, Serializer, ATTRIBUTES)(deserializer)); } else static if (isCustomSerializable!T) { alias CustomType = typeof(T.init.toRepresentation()); return T.fromRepresentation(deserializeImpl!(CustomType, Policy, Serializer, ATTRIBUTES)(deserializer)); } else static if (isISOExtStringSerializable!T) { return T.fromISOExtString(deserializer.readValue!string()); } else static if (isStringSerializable!T) { return T.fromString(deserializer.readValue!string()); } else static if (is(T == struct) || is(T == class)) { static if (is(T == class)) { if (deserializer.tryReadNull()) return null; } bool[__traits(allMembers, T).length] set; string name; T ret; static if (is(T == class)) ret = new T; static if (hasAttributeL!(AsArrayAttribute, ATTRIBUTES)) { size_t idx = 0; deserializer.readArray!T((sz){}, { static if (hasSerializableFields!T) { switch (idx++) { default: break; foreach (i, mname; SerializableFields!T) { alias TM = typeof(__traits(getMember, ret, mname)); alias TA = TypeTuple!(__traits(getAttributes, __traits(getMember, ret, mname))); case i: static if (hasAttribute!(OptionalAttribute, __traits(getMember, T, mname))) if (deserializer.tryReadNull()) return; set[i] = true; __traits(getMember, ret, mname) = deserializeImpl!(TM, Serializer, TA)(deserializer); break; } } } else { pragma(msg, "Deserializing composite type "~T.stringof~" which has no serializable fields."); } }); } else { deserializer.readDictionary!T((name) { static if (hasSerializableFields!T) { switch (name) { default: break; foreach (i, mname; SerializableFields!T) { alias TM = typeof(__traits(getMember, ret, mname)); alias TA = TypeTuple!(__traits(getAttributes, __traits(getMember, ret, mname))); enum fname = getAttribute!(T, mname, NameAttribute)(NameAttribute(underscoreStrip(mname))).name; case fname: static if (hasAttribute!(OptionalAttribute, __traits(getMember, T, mname))) if (deserializer.tryReadNull()) return; set[i] = true; __traits(getMember, ret, mname) = deserializeImpl!(TM, Policy, Serializer, TA)(deserializer); break; } } } else { pragma(msg, "Deserializing composite type "~T.stringof~" which has no serializable fields."); } }); } foreach (i, mname; SerializableFields!T) static if (!hasAttribute!(OptionalAttribute, __traits(getMember, T, mname))) enforce(set[i], "Missing non-optional field '"~mname~"' of type '"~T.stringof~"'."); return ret; } else static if (isPointer!T) { if (deserializer.tryReadNull()) return null; alias PT = PointerTarget!T; auto ret = new PT; *ret = deserializeImpl!(PT, Policy, Serializer)(deserializer); return ret; } else static if (is(T == bool) || is(T : real) || is(T : long)) { return to!T(deserializeImpl!(string, Policy, Serializer)(deserializer)); } else static assert(false, "Unsupported serialization type: " ~ T.stringof); } /** Attribute for overriding the field name during (de-)serialization. */ NameAttribute name(string name) { return NameAttribute(name); } /// unittest { struct Test { @name("screen-size") int screenSize; } } /** Attribute marking a field as optional during deserialization. */ @property OptionalAttribute optional() { return OptionalAttribute(); } /// unittest { struct Test { // does not need to be present during deserialization @optional int screenSize = 100; } } /** Attribute for marking non-serialized fields. */ @property IgnoreAttribute ignore() { return IgnoreAttribute(); } /// unittest { struct Test { // is neither serialized not deserialized @ignore int screenSize; } } /** Attribute for forcing serialization of enum fields by name instead of by value. */ @property ByNameAttribute byName() { return ByNameAttribute(); } /// unittest { enum Color { red, green, blue } struct Test { // serialized as an int (e.g. 1 for Color.green) Color color; // serialized as a string (e.g. "green" for Color.green) @byName Color namedColor; // serialized as array of ints Color[] colorArray; // serialized as array of strings @byName Color[] namedColorArray; } } /** Attribute for representing a struct/class as an array instead of an object. Usually structs and class objects are serialized as dictionaries mapping from field name to value. Using this attribute, they will be serialized as a flat array instead. Note that changing the layout will make any already serialized data mismatch when this attribute is used. */ @property AsArrayAttribute asArray() { return AsArrayAttribute(); } /// unittest { struct Fields { int f1; string f2; double f3; } struct Test { // serialized as name:value pairs ["f1": int, "f2": string, "f3": double] Fields object; // serialized as a sequential list of values [int, string, double] @asArray Fields array; } import dub.internal.vibecompat.data.json; static assert(is(typeof(serializeToJson(Test())))); } /// enum FieldExistence { missing, exists, defer } /// User defined attribute (not intended for direct use) struct NameAttribute { string name; } /// ditto struct OptionalAttribute {} /// ditto struct IgnoreAttribute {} /// ditto struct ByNameAttribute {} /// ditto struct AsArrayAttribute {} /** Checks if a given type has a custom serialization representation. A class or struct type is custom serializable if it defines a pair of `toRepresentation`/`fromRepresentation` methods. Any class or struct type that has this trait will be serialized by using the return value of it's `toRepresentation` method instead of the original value. This trait has precedence over `isISOExtStringSerializable` and `isStringSerializable`. */ template isCustomSerializable(T) { enum bool isCustomSerializable = is(typeof(T.init.toRepresentation())) && is(typeof(T.fromRepresentation(T.init.toRepresentation())) == T); } /// unittest { // represented as a single uint when serialized static struct S { ushort x, y; uint toRepresentation() const { return x + (y << 16); } static S fromRepresentation(uint i) { return S(i & 0xFFFF, i >> 16); } } static assert(isCustomSerializable!S); } /** Checks if a given type has an ISO extended string serialization representation. A class or struct type is ISO extended string serializable if it defines a pair of `toISOExtString`/`fromISOExtString` methods. Any class or struct type that has this trait will be serialized by using the return value of it's `toISOExtString` method instead of the original value. This is mainly useful for supporting serialization of the the date/time types in `std.datetime`. This trait has precedence over `isStringSerializable`. */ template isISOExtStringSerializable(T) { enum bool isISOExtStringSerializable = is(typeof(T.init.toISOExtString()) == string) && is(typeof(T.fromISOExtString("")) == T); } /// unittest { import std.datetime; static assert(isISOExtStringSerializable!DateTime); static assert(isISOExtStringSerializable!SysTime); // represented as an ISO extended string when serialized static struct S { // dummy example implementations string toISOExtString() const { return ""; } static S fromISOExtString(string s) { return S.init; } } static assert(isISOExtStringSerializable!S); } /** Checks if a given type has a string serialization representation. A class or struct type is string serializable if it defines a pair of `toString`/`fromString` methods. Any class or struct type that has this trait will be serialized by using the return value of it's `toString` method instead of the original value. */ template isStringSerializable(T) { enum bool isStringSerializable = is(typeof(T.init.toString()) == string) && is(typeof(T.fromString("")) == T); } /// unittest { import std.conv; // represented as the boxed value when serialized static struct Box(T) { T value; } template BoxPol(S) { auto toRepresentation(S s) { return s.value; } S fromRepresentation(typeof(S.init.value) v) { return S(v); } } static assert(isPolicySerializable!(BoxPol, Box!int)); } private template DefaultPolicy(T) { } /** Checks if a given policy supports custom serialization for a given type. A class or struct type is custom serializable according to a policy if the policy defines a pair of `toRepresentation`/`fromRepresentation` functions. Any class or struct type that has this trait for the policy supplied to `serializeWithPolicy` will be serialized by using the return value of the policy `toRepresentation` function instead of the original value. This trait has precedence over `isCustomSerializable`, `isISOExtStringSerializable` and `isStringSerializable`. See_Also: `vibe.data.serialization.serializeWithPolicy` */ template isPolicySerializable(alias Policy, T) { enum bool isPolicySerializable = is(typeof(Policy!T.toRepresentation(T.init))) && is(typeof(Policy!T.fromRepresentation(Policy!T.toRepresentation(T.init))) == T); } /// unittest { import std.conv; // represented as a string when serialized static struct S { int value; // dummy example implementations string toString() const { return value.to!string(); } static S fromString(string s) { return S(s.to!int()); } } static assert(isStringSerializable!S); } /** Chains serialization policy. Constructs a serialization policy that given a type `T` will apply the first compatible policy `toRepresentation` and `fromRepresentation` functions. Policies are evaluated left-to-right according to `isPolicySerializable`. See_Also: `vibe.data.serialization.serializeWithPolicy` */ template ChainedPolicy(alias Primary, Fallbacks...) { static if (Fallbacks.length == 0) { alias ChainedPolicy = Primary; } else { alias ChainedPolicy = ChainedPolicy!(ChainedPolicyImpl!(Primary, Fallbacks[0]), Fallbacks[1..$]); } } /// unittest { import std.conv; // To be represented as the boxed value when serialized static struct Box(T) { T value; } // Also to berepresented as the boxed value when serialized, but has // a different way to access the value. static struct Box2(T) { private T v; ref T get() { return v; } } template BoxPol(S) { auto toRepresentation(S s) { return s.value; } S fromRepresentation(typeof(toRepresentation(S.init)) v) { return S(v); } } template Box2Pol(S) { auto toRepresentation(S s) { return s.get(); } S fromRepresentation(typeof(toRepresentation(S.init)) v) { S s; s.get() = v; return s; } } alias ChainPol = ChainedPolicy!(BoxPol, Box2Pol); static assert(!isPolicySerializable!(BoxPol, Box2!int)); static assert(!isPolicySerializable!(Box2Pol, Box!int)); static assert(isPolicySerializable!(ChainPol, Box!int)); static assert(isPolicySerializable!(ChainPol, Box2!int)); } private template ChainedPolicyImpl(alias Primary, alias Fallback) { template Pol(T) { static if (isPolicySerializable!(Primary, T)) { alias toRepresentation = Primary!T.toRepresentation; alias fromRepresentation = Primary!T.fromRepresentation; } else { alias toRepresentation = Fallback!T.toRepresentation; alias fromRepresentation = Fallback!T.fromRepresentation; } } alias ChainedPolicyImpl = Pol; } private template hasAttribute(T, alias decl) { enum hasAttribute = findFirstUDA!(T, decl).found; } unittest { @asArray int i1; static assert(hasAttribute!(AsArrayAttribute, i1)); int i2; static assert(!hasAttribute!(AsArrayAttribute, i2)); } private template hasAttributeL(T, ATTRIBUTES...) { static if (ATTRIBUTES.length == 1) { enum hasAttributeL = is(typeof(ATTRIBUTES[0]) == T); } else static if (ATTRIBUTES.length > 1) { enum hasAttributeL = hasAttributeL!(T, ATTRIBUTES[0 .. $/2]) || hasAttributeL!(T, ATTRIBUTES[$/2 .. $]); } else { enum hasAttributeL = false; } } unittest { static assert(hasAttributeL!(AsArrayAttribute, byName, asArray)); static assert(!hasAttributeL!(AsArrayAttribute, byName)); } private static T getAttribute(TT, string mname, T)(T default_value) { enum val = findFirstUDA!(T, __traits(getMember, TT, mname)); static if (val.found) return val.value; else return default_value; } private string underscoreStrip(string field_name) { if( field_name.length < 1 || field_name[$-1] != '_' ) return field_name; else return field_name[0 .. $-1]; } private template hasSerializableFields(T, size_t idx = 0) { enum hasSerializableFields = SerializableFields!(T).length > 0; /*static if (idx < __traits(allMembers, T).length) { enum mname = __traits(allMembers, T)[idx]; static if (!isRWPlainField!(T, mname) && !isRWField!(T, mname)) enum hasSerializableFields = hasSerializableFields!(T, idx+1); else static if (hasAttribute!(IgnoreAttribute, __traits(getMember, T, mname))) enum hasSerializableFields = hasSerializableFields!(T, idx+1); else enum hasSerializableFields = true; } else enum hasSerializableFields = false;*/ } private template SerializableFields(COMPOSITE) { alias SerializableFields = FilterSerializableFields!(COMPOSITE, __traits(allMembers, COMPOSITE)); } private template FilterSerializableFields(COMPOSITE, FIELDS...) { static if (FIELDS.length > 1) { alias FilterSerializableFields = TypeTuple!( FilterSerializableFields!(COMPOSITE, FIELDS[0 .. $/2]), FilterSerializableFields!(COMPOSITE, FIELDS[$/2 .. $])); } else static if (FIELDS.length == 1) { alias T = COMPOSITE; enum mname = FIELDS[0]; static if (isRWPlainField!(T, mname) || isRWField!(T, mname)) { alias Tup = TypeTuple!(__traits(getMember, COMPOSITE, FIELDS[0])); static if (Tup.length != 1) { alias FilterSerializableFields = TypeTuple!(mname); } else { static if (!hasAttribute!(IgnoreAttribute, __traits(getMember, T, mname))) alias FilterSerializableFields = TypeTuple!(mname); else alias FilterSerializableFields = TypeTuple!(); } } else alias FilterSerializableFields = TypeTuple!(); } else alias FilterSerializableFields = TypeTuple!(); } private size_t getExpandedFieldCount(T, FIELDS...)() { size_t ret = 0; foreach (F; FIELDS) ret += TypeTuple!(__traits(getMember, T, F)).length; return ret; } /******************************************************************************/ /* General serialization unit testing */ /******************************************************************************/ version (unittest) { private struct TestSerializer { import std.array, std.conv, std.string; string result; enum isSupportedValueType(T) = is(T == string) || is(T == typeof(null)) || is(T == float) || is (T == int); string getSerializedResult() { return result; } void beginWriteDictionary(T)() { result ~= "D("~T.mangleof~"){"; } void endWriteDictionary(T)() { result ~= "}D("~T.mangleof~")"; } void beginWriteDictionaryEntry(T)(string name) { result ~= "DE("~T.mangleof~","~name~")("; } void endWriteDictionaryEntry(T)(string name) { result ~= ")DE("~T.mangleof~","~name~")"; } void beginWriteArray(T)(size_t length) { result ~= "A("~T.mangleof~")["~length.to!string~"]["; } void endWriteArray(T)() { result ~= "]A("~T.mangleof~")"; } void beginWriteArrayEntry(T)(size_t i) { result ~= "AE("~T.mangleof~","~i.to!string~")("; } void endWriteArrayEntry(T)(size_t i) { result ~= ")AE("~T.mangleof~","~i.to!string~")"; } void writeValue(T)(T value) { if (is(T == typeof(null))) result ~= "null"; else { assert(isSupportedValueType!T); result ~= "V("~T.mangleof~")("~value.to!string~")"; } } // deserialization void readDictionary(T)(scope void delegate(string) entry_callback) { skip("D("~T.mangleof~"){"); while (result.startsWith("DE(")) { result = result[3 .. $]; auto idx = result.indexOf(','); auto idx2 = result.indexOf(")("); assert(idx > 0 && idx2 > idx); auto t = result[0 .. idx]; auto n = result[idx+1 .. idx2]; result = result[idx2+2 .. $]; entry_callback(n); skip(")DE("~t~","~n~")"); } skip("}D("~T.mangleof~")"); } void readArray(T)(scope void delegate(size_t) size_callback, scope void delegate() entry_callback) { skip("A("~T.mangleof~")["); auto bidx = result.indexOf("]["); assert(bidx > 0); auto cnt = result[0 .. bidx].to!size_t; result = result[bidx+2 .. $]; size_t i = 0; while (result.startsWith("AE(")) { result = result[3 .. $]; auto idx = result.indexOf(','); auto idx2 = result.indexOf(")("); assert(idx > 0 && idx2 > idx); auto t = result[0 .. idx]; auto n = result[idx+1 .. idx2]; result = result[idx2+2 .. $]; assert(n == i.to!string); entry_callback(); skip(")AE("~t~","~n~")"); i++; } skip("]A("~T.mangleof~")"); assert(i == cnt); } T readValue(T)() { skip("V("~T.mangleof~")("); auto idx = result.indexOf(')'); assert(idx >= 0); auto ret = result[0 .. idx].to!T; result = result[idx+1 .. $]; return ret; } void skip(string prefix) { assert(result.startsWith(prefix), result); result = result[prefix.length .. $]; } bool tryReadNull() { if (result.startsWith("null")) { result = result[4 .. $]; return true; } else return false; } } } unittest { // basic serialization behavior import std.typecons : Nullable; static void test(T)(T value, string expected) { assert(serialize!TestSerializer(value) == expected, serialize!TestSerializer(value)); static if (isPointer!T) { if (value) assert(*deserialize!(TestSerializer, T)(expected) == *value); else assert(deserialize!(TestSerializer, T)(expected) is null); } else static if (is(T == Nullable!U, U)) { if (value.isNull()) assert(deserialize!(TestSerializer, T)(expected).isNull); else assert(deserialize!(TestSerializer, T)(expected) == value); } else assert(deserialize!(TestSerializer, T)(expected) == value); } test("hello", "V(Aya)(hello)"); test(12, "V(i)(12)"); test(12.0, "V(Aya)(12)"); test(12.0f, "V(f)(12)"); assert(serialize!TestSerializer(null) == "null"); test(["hello", "world"], "A(AAya)[2][AE(Aya,0)(V(Aya)(hello))AE(Aya,0)AE(Aya,1)(V(Aya)(world))AE(Aya,1)]A(AAya)"); string mangleOfAA = (string[string]).mangleof; test(["hello": "world"], "D(" ~ mangleOfAA ~ "){DE(Aya,hello)(V(Aya)(world))DE(Aya,hello)}D(" ~ mangleOfAA ~ ")"); test(cast(int*)null, "null"); int i = 42; test(&i, "V(i)(42)"); Nullable!int j; test(j, "null"); j = 42; test(j, "V(i)(42)"); } unittest { // basic user defined types static struct S { string f; } enum Sm = S.mangleof; auto s = S("hello"); enum s_ser = "D("~Sm~"){DE(Aya,f)(V(Aya)(hello))DE(Aya,f)}D("~Sm~")"; assert(serialize!TestSerializer(s) == s_ser, serialize!TestSerializer(s)); assert(deserialize!(TestSerializer, S)(s_ser) == s); static class C { string f; } enum Cm = C.mangleof; C c; assert(serialize!TestSerializer(c) == "null"); c = new C; c.f = "hello"; enum c_ser = "D("~Cm~"){DE(Aya,f)(V(Aya)(hello))DE(Aya,f)}D("~Cm~")"; assert(serialize!TestSerializer(c) == c_ser); assert(deserialize!(TestSerializer, C)(c_ser).f == c.f); enum E { hello, world } assert(serialize!TestSerializer(E.hello) == "V(i)(0)"); assert(serialize!TestSerializer(E.world) == "V(i)(1)"); } unittest { // tuple serialization import std.typecons : Tuple; static struct S(T...) { T f; } enum Sm = S!(int, string).mangleof; enum Tum = Tuple!(int, string).mangleof; auto s = S!(int, string)(42, "hello"); assert(serialize!TestSerializer(s) == "D("~Sm~"){DE("~Tum~",f)(A("~Tum~")[2][AE(i,0)(V(i)(42))AE(i,0)AE(Aya,1)(V(Aya)(hello))AE(Aya,1)]A("~Tum~"))DE("~Tum~",f)}D("~Sm~")"); static struct T { @asArray S!(int, string) g; } enum Tm = T.mangleof; auto t = T(s); assert(serialize!TestSerializer(t) == "D("~Tm~"){DE("~Sm~",g)(A("~Sm~")[2][AE(i,0)(V(i)(42))AE(i,0)AE(Aya,1)(V(Aya)(hello))AE(Aya,1)]A("~Sm~"))DE("~Sm~",g)}D("~Tm~")"); } unittest { // testing the various UDAs enum E { hello, world } enum Em = E.mangleof; static struct S { @byName E e; @ignore int i; @optional float f; } enum Sm = S.mangleof; auto s = S(E.world, 42, 1.0f); assert(serialize!TestSerializer(s) == "D("~Sm~"){DE("~Em~",e)(V(Aya)(world))DE("~Em~",e)DE(f,f)(V(f)(1))DE(f,f)}D("~Sm~")"); } unittest { // custom serialization support // iso-ext import std.datetime; auto t = TimeOfDay(6, 31, 23); assert(serialize!TestSerializer(t) == "V(Aya)(06:31:23)"); auto d = Date(1964, 1, 23); assert(serialize!TestSerializer(d) == "V(Aya)(1964-01-23)"); auto dt = DateTime(d, t); assert(serialize!TestSerializer(dt) == "V(Aya)(1964-01-23T06:31:23)"); auto st = SysTime(dt, UTC()); assert(serialize!TestSerializer(st) == "V(Aya)(1964-01-23T06:31:23Z)"); // string struct S1 { int i; string toString() const { return "hello"; } static S1 fromString(string) { return S1.init; } } struct S2 { int i; string toString() const { return "hello"; } } enum S2m = S2.mangleof; struct S3 { int i; static S3 fromString(string) { return S3.init; } } enum S3m = S3.mangleof; assert(serialize!TestSerializer(S1.init) == "V(Aya)(hello)"); assert(serialize!TestSerializer(S2.init) == "D("~S2m~"){DE(i,i)(V(i)(0))DE(i,i)}D("~S2m~")"); assert(serialize!TestSerializer(S3.init) == "D("~S3m~"){DE(i,i)(V(i)(0))DE(i,i)}D("~S3m~")"); // custom struct C1 { int i; float toRepresentation() const { return 1.0f; } static C1 fromRepresentation(float f) { return C1.init; } } struct C2 { int i; float toRepresentation() const { return 1.0f; } } enum C2m = C2.mangleof; struct C3 { int i; static C3 fromRepresentation(float f) { return C3.init; } } enum C3m = C3.mangleof; assert(serialize!TestSerializer(C1.init) == "V(f)(1)"); assert(serialize!TestSerializer(C2.init) == "D("~C2m~"){DE(i,i)(V(i)(0))DE(i,i)}D("~C2m~")"); assert(serialize!TestSerializer(C3.init) == "D("~C3m~"){DE(i,i)(V(i)(0))DE(i,i)}D("~C3m~")"); } unittest // Testing corner case: member function returning by ref { import dub.internal.vibecompat.data.json; static struct S { int i; ref int foo() { return i; } } static assert(__traits(compiles, { S().serializeToJson(); })); static assert(__traits(compiles, { Json().deserializeJson!S(); })); auto s = S(1); assert(s.serializeToJson().deserializeJson!S() == s); } unittest // Testing corner case: Variadic template constructors and methods { import dub.internal.vibecompat.data.json; static struct S { int i; this(Args...)(Args args) {} int foo(Args...)(Args args) { return i; } ref int bar(Args...)(Args args) { return i; } } static assert(__traits(compiles, { S().serializeToJson(); })); static assert(__traits(compiles, { Json().deserializeJson!S(); })); auto s = S(1); assert(s.serializeToJson().deserializeJson!S() == s); } unittest // Make sure serializing through properties still works { import dub.internal.vibecompat.data.json; static struct S { public int i; private int privateJ; @property int j() { return privateJ; } @property void j(int j) { privateJ = j; } } auto s = S(1, 2); assert(s.serializeToJson().deserializeJson!S() == s); } unittest { // test BitFlags serialization import std.typecons : BitFlags; enum Flag { a = 1<<0, b = 1<<1, c = 1<<2 } enum Flagm = Flag.mangleof; alias Flags = BitFlags!Flag; enum Flagsm = Flags.mangleof; enum Fi_ser = "A(A"~Flagm~")[0][]A(A"~Flagm~")"; assert(serialize!TestSerializer(Flags.init) == Fi_ser); enum Fac_ser = "A(A"~Flagm~")[2][AE("~Flagm~",0)(V(i)(1))AE("~Flagm~",0)AE("~Flagm~",1)(V(i)(4))AE("~Flagm~",1)]A(A"~Flagm~")"; assert(serialize!TestSerializer(Flags(Flag.a, Flag.c)) == Fac_ser); struct S { @byName Flags f; } enum Sm = S.mangleof; enum Sac_ser = "D("~Sm~"){DE("~Flagsm~",f)(A(A"~Flagm~")[2][AE("~Flagm~",0)(V(Aya)(a))AE("~Flagm~",0)AE("~Flagm~",1)(V(Aya)(c))AE("~Flagm~",1)]A(A"~Flagm~"))DE("~Flagsm~",f)}D("~Sm~")"; assert(serialize!TestSerializer(S(Flags(Flag.a, Flag.c))) == Sac_ser); assert(deserialize!(TestSerializer, Flags)(Fi_ser) == Flags.init); assert(deserialize!(TestSerializer, Flags)(Fac_ser) == Flags(Flag.a, Flag.c)); assert(deserialize!(TestSerializer, S)(Sac_ser) == S(Flags(Flag.a, Flag.c))); } dub-1.19.0/source/dub/internal/vibecompat/data/utils.d000066400000000000000000000450401360435400500226140ustar00rootroot00000000000000/** Utility functions for data serialization Copyright: © 2012 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.internal.vibecompat.data.utils; version (Have_vibe_d_data) {} else: public import std.traits; /** Checks if given type is a getter function type Returns: `true` if argument is a getter */ template isPropertyGetter(T...) if (T.length == 1) { import std.traits : functionAttributes, FunctionAttribute, ReturnType, isSomeFunction; static if (isSomeFunction!(T[0])) { enum isPropertyGetter = (functionAttributes!(T[0]) & FunctionAttribute.property) != 0 && !is(ReturnType!T == void); } else enum isPropertyGetter = false; } /// unittest { interface Test { @property int getter(); @property void setter(int); int simple(); } static assert(isPropertyGetter!(typeof(&Test.getter))); static assert(!isPropertyGetter!(typeof(&Test.setter))); static assert(!isPropertyGetter!(typeof(&Test.simple))); static assert(!isPropertyGetter!int); } /** Checks if given type is a setter function type Returns: `true` if argument is a setter */ template isPropertySetter(T...) if (T.length == 1) { import std.traits : functionAttributes, FunctionAttribute, ReturnType, isSomeFunction; static if (isSomeFunction!(T[0])) { enum isPropertySetter = (functionAttributes!(T) & FunctionAttribute.property) != 0 && is(ReturnType!(T[0]) == void); } else enum isPropertySetter = false; } /// unittest { interface Test { @property int getter(); @property void setter(int); int simple(); } static assert(isPropertySetter!(typeof(&Test.setter))); static assert(!isPropertySetter!(typeof(&Test.getter))); static assert(!isPropertySetter!(typeof(&Test.simple))); static assert(!isPropertySetter!int); } /** Deduces single base interface for a type. Multiple interfaces will result in compile-time error. Params: T = interface or class type Returns: T if it is an interface. If T is a class, interface it implements. */ template baseInterface(T) if (is(T == interface) || is(T == class)) { import std.traits : InterfacesTuple; static if (is(T == interface)) { alias baseInterface = T; } else { alias Ifaces = InterfacesTuple!T; static assert ( Ifaces.length == 1, "Type must be either provided as an interface or implement only one interface" ); alias baseInterface = Ifaces[0]; } } /// unittest { interface I1 { } class A : I1 { } interface I2 { } class B : I1, I2 { } static assert (is(baseInterface!I1 == I1)); static assert (is(baseInterface!A == I1)); static assert (!is(typeof(baseInterface!B))); } /** Determins if a member is a public, non-static data field. */ template isRWPlainField(T, string M) { static if (!isRWField!(T, M)) enum isRWPlainField = false; else { //pragma(msg, T.stringof~"."~M~":"~typeof(__traits(getMember, T, M)).stringof); enum isRWPlainField = __traits(compiles, *(&__traits(getMember, Tgen!T(), M)) = *(&__traits(getMember, Tgen!T(), M))); } } /** Determines if a member is a public, non-static, de-facto data field. In addition to plain data fields, R/W properties are also accepted. */ template isRWField(T, string M) { import std.traits; import std.typetuple; static void testAssign()() { T t = void; __traits(getMember, t, M) = __traits(getMember, t, M); } // reject type aliases static if (is(TypeTuple!(__traits(getMember, T, M)))) enum isRWField = false; // reject non-public members else static if (!isPublicMember!(T, M)) enum isRWField = false; // reject static members else static if (!isNonStaticMember!(T, M)) enum isRWField = false; // reject non-typed members else static if (!is(typeof(__traits(getMember, T, M)))) enum isRWField = false; // reject void typed members (includes templates) else static if (is(typeof(__traits(getMember, T, M)) == void)) enum isRWField = false; // reject non-assignable members else static if (!__traits(compiles, testAssign!()())) enum isRWField = false; else static if (anySatisfy!(isSomeFunction, __traits(getMember, T, M))) { // If M is a function, reject if not @property or returns by ref private enum FA = functionAttributes!(__traits(getMember, T, M)); enum isRWField = (FA & FunctionAttribute.property) != 0; } else { enum isRWField = true; } } unittest { import std.algorithm; struct S { alias a = int; // alias int i; // plain RW field enum j = 42; // manifest constant static int k = 42; // static field private int privateJ; // private RW field this(Args...)(Args args) {} // read-write property (OK) @property int p1() { return privateJ; } @property void p1(int j) { privateJ = j; } // read-only property (NO) @property int p2() { return privateJ; } // write-only property (NO) @property void p3(int value) { privateJ = value; } // ref returning property (OK) @property ref int p4() { return i; } // parameter-less template property (OK) @property ref int p5()() { return i; } // not treated as a property by DMD, so not a field @property int p6()() { return privateJ; } @property void p6(int j)() { privateJ = j; } static @property int p7() { return k; } static @property void p7(int value) { k = value; } ref int f1() { return i; } // ref returning function (no field) int f2(Args...)(Args args) { return i; } ref int f3(Args...)(Args args) { return i; } void someMethod() {} ref int someTempl()() { return i; } } immutable plainFields = ["i"]; immutable fields = ["i", "p1", "p4", "p5"]; foreach (mem; __traits(allMembers, S)) { static if (isRWField!(S, mem)) static assert(fields.canFind(mem), mem~" detected as field."); else static assert(!fields.canFind(mem), mem~" not detected as field."); static if (isRWPlainField!(S, mem)) static assert(plainFields.canFind(mem), mem~" not detected as plain field."); else static assert(!plainFields.canFind(mem), mem~" not detected as plain field."); } } package T Tgen(T)(){ return T.init; } /** Tests if the protection of a member is public. */ template isPublicMember(T, string M) { import std.algorithm, std.typetuple : TypeTuple; static if (!__traits(compiles, TypeTuple!(__traits(getMember, T, M)))) enum isPublicMember = false; else { alias MEM = TypeTuple!(__traits(getMember, T, M)); enum _prot = __traits(getProtection, MEM); enum isPublicMember = _prot == "public" || _prot == "export"; } } unittest { class C { int a; export int b; protected int c; private int d; package int e; void f() {} static void g() {} private void h() {} private static void i() {} } static assert (isPublicMember!(C, "a")); static assert (isPublicMember!(C, "b")); static assert (!isPublicMember!(C, "c")); static assert (!isPublicMember!(C, "d")); static assert (!isPublicMember!(C, "e")); static assert (isPublicMember!(C, "f")); static assert (isPublicMember!(C, "g")); static assert (!isPublicMember!(C, "h")); static assert (!isPublicMember!(C, "i")); struct S { int a; export int b; private int d; package int e; } static assert (isPublicMember!(S, "a")); static assert (isPublicMember!(S, "b")); static assert (!isPublicMember!(S, "d")); static assert (!isPublicMember!(S, "e")); S s; s.a = 21; assert(s.a == 21); } /** Tests if a member requires $(D this) to be used. */ template isNonStaticMember(T, string M) { import std.typetuple; import std.traits; alias MF = TypeTuple!(__traits(getMember, T, M)); static if (M.length == 0) { enum isNonStaticMember = false; } else static if (anySatisfy!(isSomeFunction, MF)) { enum isNonStaticMember = !__traits(isStaticFunction, MF); } else { enum isNonStaticMember = !__traits(compiles, (){ auto x = __traits(getMember, T, M); }()); } } unittest { // normal fields struct S { int a; static int b; enum c = 42; void f(); static void g(); ref int h() { return a; } static ref int i() { return b; } } static assert(isNonStaticMember!(S, "a")); static assert(!isNonStaticMember!(S, "b")); static assert(!isNonStaticMember!(S, "c")); static assert(isNonStaticMember!(S, "f")); static assert(!isNonStaticMember!(S, "g")); static assert(isNonStaticMember!(S, "h")); static assert(!isNonStaticMember!(S, "i")); } unittest { // tuple fields struct S(T...) { T a; static T b; } alias T = S!(int, float); auto p = T.b; static assert(isNonStaticMember!(T, "a")); static assert(!isNonStaticMember!(T, "b")); alias U = S!(); static assert(!isNonStaticMember!(U, "a")); static assert(!isNonStaticMember!(U, "b")); } /** Tests if a Group of types is implicitly convertible to a Group of target types. */ bool areConvertibleTo(alias TYPES, alias TARGET_TYPES)() if (isGroup!TYPES && isGroup!TARGET_TYPES) { static assert(TYPES.expand.length == TARGET_TYPES.expand.length); foreach (i, V; TYPES.expand) if (!is(V : TARGET_TYPES.expand[i])) return false; return true; } /// Test if the type $(D DG) is a correct delegate for an opApply where the /// key/index is of type $(D TKEY) and the value of type $(D TVALUE). template isOpApplyDg(DG, TKEY, TVALUE) { import std.traits; static if (is(DG == delegate) && is(ReturnType!DG : int)) { private alias PTT = ParameterTypeTuple!(DG); private alias PSCT = ParameterStorageClassTuple!(DG); private alias STC = ParameterStorageClass; // Just a value static if (PTT.length == 1) { enum isOpApplyDg = (is(PTT[0] == TVALUE) && PSCT[0] == STC.ref_); } else static if (PTT.length == 2) { enum isOpApplyDg = (is(PTT[0] == TKEY) && PSCT[0] == STC.ref_) && (is(PTT[1] == TKEY) && PSCT[1] == STC.ref_); } else enum isOpApplyDg = false; } else { enum isOpApplyDg = false; } } /** TypeTuple which does not auto-expand. Useful when you need to multiple several type tuples as different template argument list parameters, without merging those. */ template Group(T...) { alias expand = T; } /// unittest { alias group = Group!(int, double, string); static assert (!is(typeof(group.length))); static assert (group.expand.length == 3); static assert (is(group.expand[1] == double)); } /** */ template isGroup(T...) { static if (T.length != 1) enum isGroup = false; else enum isGroup = !is(T[0]) && is(typeof(T[0]) == void) // does not evaluate to something && is(typeof(T[0].expand.length) : size_t) // expands to something with length && !is(typeof(&(T[0].expand))); // expands to not addressable } version (unittest) // NOTE: GDC complains about template definitions in unittest blocks { import std.typetuple; alias group = Group!(int, double, string); alias group2 = Group!(); template Fake(T...) { int[] expand; } alias fake = Fake!(int, double, string); alias fake2 = TypeTuple!(int, double, string); static assert (isGroup!group); static assert (isGroup!group2); static assert (!isGroup!fake); static assert (!isGroup!fake2); } /* Copied from Phobos as it is private there. */ private template isSame(ab...) if (ab.length == 2) { static if (is(ab[0]) && is(ab[1])) { enum isSame = is(ab[0] == ab[1]); } else static if (!is(ab[0]) && !is(ab[1]) && is(typeof(ab[0] == ab[1]) == bool) && (ab[0] == ab[1])) { static if (!__traits(compiles, &ab[0]) || !__traits(compiles, &ab[1])) enum isSame = (ab[0] == ab[1]); else enum isSame = __traits(isSame, ab[0], ab[1]); } else { enum isSame = __traits(isSame, ab[0], ab[1]); } } /** Small convenience wrapper to find and extract certain UDA from given type. Will stop on first element which is of required type. Params: UDA = type or template to search for in UDA list Symbol = symbol to query for UDA's allow_types = if set to `false` considers attached `UDA` types an error (only accepts instances/values) Returns: aggregated search result struct with 3 field. `value` aliases found UDA. `found` is boolean flag for having a valid find. `index` is integer index in attribute list this UDA was found at. */ template findFirstUDA(alias UDA, alias Symbol, bool allow_types = false) if (!is(UDA)) { enum findFirstUDA = findNextUDA!(UDA, Symbol, 0, allow_types); } /// Ditto template findFirstUDA(UDA, alias Symbol, bool allow_types = false) { enum findFirstUDA = findNextUDA!(UDA, Symbol, 0, allow_types); } private struct UdaSearchResult(alias UDA) { alias value = UDA; bool found = false; long index = -1; } /** Small convenience wrapper to find and extract certain UDA from given type. Will start at the given index and stop on the next element which is of required type. Params: UDA = type or template to search for in UDA list Symbol = symbol to query for UDA's idx = 0-based index to start at. Should be positive, and under the total number of attributes. allow_types = if set to `false` considers attached `UDA` types an error (only accepts instances/values) Returns: aggregated search result struct with 3 field. `value` aliases found UDA. `found` is boolean flag for having a valid find. `index` is integer index in attribute list this UDA was found at. */ template findNextUDA(alias UDA, alias Symbol, long idx, bool allow_types = false) if (!is(UDA)) { import std.traits : isInstanceOf; import std.typetuple : TypeTuple; private alias udaTuple = TypeTuple!(__traits(getAttributes, Symbol)); static assert(idx >= 0, "Index given to findNextUDA can't be negative"); static assert(idx <= udaTuple.length, "Index given to findNextUDA is above the number of attribute"); public template extract(size_t index, list...) { static if (!list.length) enum extract = UdaSearchResult!(null)(false, -1); else { static if (is(list[0])) { static if (is(UDA) && is(list[0] == UDA) || !is(UDA) && isInstanceOf!(UDA, list[0])) { static assert (allow_types, "findNextUDA is designed to look up values, not types"); enum extract = UdaSearchResult!(list[0])(true, index); } else enum extract = extract!(index + 1, list[1..$]); } else { static if (is(UDA) && is(typeof(list[0]) == UDA) || !is(UDA) && isInstanceOf!(UDA, typeof(list[0]))) { import vibe.internal.meta.traits : isPropertyGetter; static if (isPropertyGetter!(list[0])) { enum value = list[0]; enum extract = UdaSearchResult!(value)(true, index); } else enum extract = UdaSearchResult!(list[0])(true, index); } else enum extract = extract!(index + 1, list[1..$]); } } } enum findNextUDA = extract!(idx, udaTuple[idx .. $]); } /// ditto template findNextUDA(UDA, alias Symbol, long idx, bool allow_types = false) { import std.traits : isInstanceOf; import std.typetuple : TypeTuple; private alias udaTuple = TypeTuple!(__traits(getAttributes, Symbol)); static assert(idx >= 0, "Index given to findNextUDA can't be negative"); static assert(idx <= udaTuple.length, "Index given to findNextUDA is above the number of attribute"); public template extract(size_t index, list...) { static if (!list.length) enum extract = UdaSearchResult!(null)(false, -1); else { static if (is(list[0])) { static if (is(list[0] == UDA)) { static assert (allow_types, "findNextUDA is designed to look up values, not types"); enum extract = UdaSearchResult!(list[0])(true, index); } else enum extract = extract!(index + 1, list[1..$]); } else { static if (is(typeof(list[0]) == UDA)) { static if (isPropertyGetter!(list[0])) { enum value = list[0]; enum extract = UdaSearchResult!(value)(true, index); } else enum extract = UdaSearchResult!(list[0])(true, index); } else enum extract = extract!(index + 1, list[1..$]); } } } enum findNextUDA = extract!(idx, udaTuple[idx .. $]); } /// unittest { struct Attribute { int x; } @("something", Attribute(42), Attribute(41)) void symbol(); enum result0 = findNextUDA!(string, symbol, 0); static assert (result0.found); static assert (result0.index == 0); static assert (result0.value == "something"); enum result1 = findNextUDA!(Attribute, symbol, 0); static assert (result1.found); static assert (result1.index == 1); static assert (result1.value == Attribute(42)); enum result2 = findNextUDA!(int, symbol, 0); static assert (!result2.found); enum result3 = findNextUDA!(Attribute, symbol, result1.index + 1); static assert (result3.found); static assert (result3.index == 2); static assert (result3.value == Attribute(41)); } unittest { struct Attribute { int x; } @(Attribute) void symbol(); static assert (!is(findNextUDA!(Attribute, symbol, 0))); enum result0 = findNextUDA!(Attribute, symbol, 0, true); static assert (result0.found); static assert (result0.index == 0); static assert (is(result0.value == Attribute)); } unittest { struct Attribute { int x; } enum Dummy; @property static Attribute getter() { return Attribute(42); } @Dummy @getter void symbol(); enum result0 = findNextUDA!(Attribute, symbol, 0); static assert (result0.found); static assert (result0.index == 1); static assert (result0.value == Attribute(42)); } /// Eager version of findNextUDA that represent all instances of UDA in a Tuple. /// If one of the attribute is a type instead of an instance, compilation will fail. template UDATuple(alias UDA, alias Sym) { import std.typetuple : TypeTuple; private template extract(size_t maxSize, Founds...) { private alias LastFound = Founds[$ - 1]; // No more to find static if (!LastFound.found) enum extract = Founds[0 .. $ - 1]; else { // For ease of use, this is a Tuple of UDA, not a tuple of UdaSearchResult!(...) private alias Result = TypeTuple!(Founds[0 .. $ - 1], LastFound.value); // We're at the last parameter static if (LastFound.index == maxSize) enum extract = Result; else enum extract = extract!(maxSize, Result, findNextUDA!(UDA, Sym, LastFound.index + 1)); } } private enum maxIndex = TypeTuple!(__traits(getAttributes, Sym)).length; enum UDATuple = extract!(maxIndex, findNextUDA!(UDA, Sym, 0)); } unittest { import std.typetuple : TypeTuple; struct Attribute { int x; } enum Dummy; @(Dummy, Attribute(21), Dummy, Attribute(42), Attribute(84)) void symbol() {} @(Dummy, Attribute(21), Dummy, Attribute(42), Attribute) void wrong() {} alias Cmp = TypeTuple!(Attribute(21), Attribute(42), Attribute(84)); static assert(Cmp == UDATuple!(Attribute, symbol)); static assert(!is(UDATuple!(Attribute, wrong))); } /// Avoid repeating the same error message again and again. /// ---- /// if (!__ctfe) /// assert(0, onlyAsUda!func); /// ---- template onlyAsUda(string from /*= __FUNCTION__*/) { // With default param, DMD think expression is void, even when writing 'enum string onlyAsUda = ...' enum onlyAsUda = from~" must only be used as an attribute - not called as a runtime function."; } dub-1.19.0/source/dub/internal/vibecompat/inet/000077500000000000000000000000001360435400500213325ustar00rootroot00000000000000dub-1.19.0/source/dub/internal/vibecompat/inet/path.d000066400000000000000000000370461360435400500224450ustar00rootroot00000000000000/** Contains routines for high level path handling. Copyright: © 2012 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.internal.vibecompat.inet.path; version (Have_vibe_core) public import vibe.core.path; else version (Have_vibe_d_core) public import vibe.inet.path; else: import std.algorithm; import std.array; import std.conv; import std.exception; import std.string; deprecated("Use NativePath instead.") alias Path = NativePath; /** Represents an absolute or relative file system path. This struct allows to do safe operations on paths, such as concatenation and sub paths. Checks are done to disallow invalid operations such as concatenating two absolute paths. It also validates path strings and allows for easy checking of malicious relative paths. */ struct NativePath { private { immutable(PathEntry)[] m_nodes; bool m_absolute = false; bool m_endsWithSlash = false; } alias Segment = PathEntry; alias bySegment = nodes; /// Constructs a NativePath object by parsing a path string. this(string pathstr) { m_nodes = splitPath(pathstr); m_absolute = (pathstr.startsWith("/") || m_nodes.length > 0 && (m_nodes[0].toString().countUntil(':')>0 || m_nodes[0] == "\\")); m_endsWithSlash = pathstr.endsWith("/"); } /// Constructs a path object from a list of PathEntry objects. this(immutable(PathEntry)[] nodes, bool absolute) { m_nodes = nodes; m_absolute = absolute; } /// Constructs a relative path with one path entry. this(PathEntry entry){ m_nodes = [entry]; m_absolute = false; } /// Determines if the path is absolute. @property bool absolute() const { return m_absolute; } /// Resolves all '.' and '..' path entries as far as possible. void normalize() { immutable(PathEntry)[] newnodes; foreach( n; m_nodes ){ switch(n.toString()){ default: newnodes ~= n; break; case "", ".": break; case "..": enforce(!m_absolute || newnodes.length > 0, "Path goes below root node."); if( newnodes.length > 0 && newnodes[$-1] != ".." ) newnodes = newnodes[0 .. $-1]; else newnodes ~= n; break; } } m_nodes = newnodes; } /// Converts the Path back to a string representation using slashes. string toString() const { if( m_nodes.empty ) return absolute ? "/" : ""; Appender!string ret; // for absolute paths start with / version(Windows) { // Make sure windows path isn't "DRIVE:" if( absolute && !m_nodes[0].toString().endsWith(':') ) ret.put('/'); } else { if( absolute ) { ret.put('/'); } } foreach( i, f; m_nodes ){ if( i > 0 ) ret.put('/'); ret.put(f.toString()); } if( m_nodes.length > 0 && m_endsWithSlash ) ret.put('/'); return ret.data; } /// Converts the NativePath object to a native path string (backslash as path separator on Windows). string toNativeString() const { if (m_nodes.empty) { version(Windows) { assert(!absolute, "Empty absolute path detected."); return m_endsWithSlash ? ".\\" : "."; } else return absolute ? "/" : m_endsWithSlash ? "./" : "."; } Appender!string ret; // for absolute unix paths start with / version(Posix) { if(absolute) ret.put('/'); } foreach( i, f; m_nodes ){ version(Windows) { if( i > 0 ) ret.put('\\'); } version(Posix) { if( i > 0 ) ret.put('/'); } else { enforce("Unsupported OS"); } ret.put(f.toString()); } if( m_nodes.length > 0 && m_endsWithSlash ){ version(Windows) { ret.put('\\'); } version(Posix) { ret.put('/'); } } return ret.data; } /// Tests if `rhs` is an anchestor or the same as this path. bool startsWith(const NativePath rhs) const { if( rhs.m_nodes.length > m_nodes.length ) return false; foreach( i; 0 .. rhs.m_nodes.length ) if( m_nodes[i] != rhs.m_nodes[i] ) return false; return true; } /// Computes the relative path from `parentPath` to this path. NativePath relativeTo(const NativePath parentPath) const { assert(this.absolute && parentPath.absolute, "Determining relative path between non-absolute paths."); version(Windows){ // a path such as ..\C:\windows is not valid, so force the path to stay absolute in this case if( this.absolute && !this.empty && (m_nodes[0].toString().endsWith(":") && !parentPath.startsWith(this[0 .. 1]) || m_nodes[0] == "\\" && !parentPath.startsWith(this[0 .. min(2, $)]))) { return this; } } int nup = 0; while( parentPath.length > nup && !startsWith(parentPath[0 .. parentPath.length-nup]) ){ nup++; } assert(m_nodes.length >= parentPath.length - nup); NativePath ret = NativePath(null, false); assert(m_nodes.length >= parentPath.length - nup); ret.m_endsWithSlash = true; foreach( i; 0 .. nup ) ret ~= ".."; ret ~= NativePath(m_nodes[parentPath.length-nup .. $], false); ret.m_endsWithSlash = this.m_endsWithSlash; return ret; } /// The last entry of the path @property ref immutable(PathEntry) head() const { enforce(m_nodes.length > 0, "Getting head of empty path."); return m_nodes[$-1]; } /// The parent path @property NativePath parentPath() const { return this[0 .. length-1]; } /// The ist of path entries of which this path is composed @property immutable(PathEntry)[] nodes() const { return m_nodes; } /// The number of path entries of which this path is composed @property size_t length() const { return m_nodes.length; } /// True if the path contains no entries @property bool empty() const { return m_nodes.length == 0; } /// Determines if the path ends with a slash (i.e. is a directory) @property bool endsWithSlash() const { return m_endsWithSlash; } /// ditto @property void endsWithSlash(bool v) { m_endsWithSlash = v; } /// Determines if this path goes outside of its base path (i.e. begins with '..'). @property bool external() const { return !m_absolute && m_nodes.length > 0 && m_nodes[0].m_name == ".."; } ref immutable(PathEntry) opIndex(size_t idx) const { return m_nodes[idx]; } NativePath opSlice(size_t start, size_t end) const { auto ret = NativePath(m_nodes[start .. end], start == 0 ? absolute : false); if( end == m_nodes.length ) ret.m_endsWithSlash = m_endsWithSlash; return ret; } size_t opDollar(int dim)() const if(dim == 0) { return m_nodes.length; } NativePath opBinary(string OP)(const NativePath rhs) const if( OP == "~" ) { NativePath ret; ret.m_nodes = m_nodes; ret.m_absolute = m_absolute; ret.m_endsWithSlash = rhs.m_endsWithSlash; ret.normalize(); // needed to avoid "."~".." become "" instead of ".." assert(!rhs.absolute, "Trying to append absolute path."); foreach(folder; rhs.m_nodes){ switch(folder.toString()){ default: ret.m_nodes = ret.m_nodes ~ folder; break; case "", ".": break; case "..": enforce(!ret.absolute || ret.m_nodes.length > 0, "Relative path goes below root node!"); if( ret.m_nodes.length > 0 && ret.m_nodes[$-1].toString() != ".." ) ret.m_nodes = ret.m_nodes[0 .. $-1]; else ret.m_nodes = ret.m_nodes ~ folder; break; } } return ret; } NativePath opBinary(string OP)(string rhs) const if( OP == "~" ) { assert(rhs.length > 0, "Cannot append empty path string."); return opBinary!"~"(NativePath(rhs)); } NativePath opBinary(string OP)(PathEntry rhs) const if( OP == "~" ) { assert(rhs.toString().length > 0, "Cannot append empty path string."); return opBinary!"~"(NativePath(rhs)); } void opOpAssign(string OP)(string rhs) if( OP == "~" ) { assert(rhs.length > 0, "Cannot append empty path string."); opOpAssign!"~"(NativePath(rhs)); } void opOpAssign(string OP)(PathEntry rhs) if( OP == "~" ) { assert(rhs.toString().length > 0, "Cannot append empty path string."); opOpAssign!"~"(NativePath(rhs)); } void opOpAssign(string OP)(NativePath rhs) if( OP == "~" ) { auto p = this ~ rhs; m_nodes = p.m_nodes; m_endsWithSlash = rhs.m_endsWithSlash; } /// Tests two paths for equality using '=='. bool opEquals(ref const NativePath rhs) const { if( m_absolute != rhs.m_absolute ) return false; if( m_endsWithSlash != rhs.m_endsWithSlash ) return false; if( m_nodes.length != rhs.length ) return false; foreach( i; 0 .. m_nodes.length ) if( m_nodes[i] != rhs.m_nodes[i] ) return false; return true; } /// ditto bool opEquals(const NativePath other) const { return opEquals(other); } int opCmp(ref const NativePath rhs) const { if( m_absolute != rhs.m_absolute ) return cast(int)m_absolute - cast(int)rhs.m_absolute; foreach( i; 0 .. min(m_nodes.length, rhs.m_nodes.length) ) if( m_nodes[i] != rhs.m_nodes[i] ) return m_nodes[i].opCmp(rhs.m_nodes[i]); if( m_nodes.length > rhs.m_nodes.length ) return 1; if( m_nodes.length < rhs.m_nodes.length ) return -1; return 0; } size_t toHash() const nothrow @trusted { size_t ret; auto strhash = &typeid(string).getHash; try foreach (n; nodes) ret ^= strhash(&n.m_name); catch (Exception) assert(false); if (m_absolute) ret ^= 0xfe3c1738; if (m_endsWithSlash) ret ^= 0x6aa4352d; return ret; } } struct PathEntry { private { string m_name; } this(string str) pure { assert(str.countUntil('/') < 0 && (str.countUntil('\\') < 0 || str.length == 1)); m_name = str; } string toString() const pure { return m_name; } @property string name() const { return m_name; } NativePath opBinary(string OP)(PathEntry rhs) const if( OP == "~" ) { return NativePath([this, rhs], false); } bool opEquals(ref const PathEntry rhs) const { return m_name == rhs.m_name; } bool opEquals(PathEntry rhs) const { return m_name == rhs.m_name; } bool opEquals(string rhs) const { return m_name == rhs; } int opCmp(ref const PathEntry rhs) const { return m_name.cmp(rhs.m_name); } int opCmp(string rhs) const { return m_name.cmp(rhs); } } private bool isValidFilename(string str) { foreach( ch; str ) if( ch == '/' || /*ch == ':' ||*/ ch == '\\' ) return false; return true; } /// Joins two path strings. subpath must be relative. string joinPath(string basepath, string subpath) { NativePath p1 = NativePath(basepath); NativePath p2 = NativePath(subpath); return (p1 ~ p2).toString(); } /// Splits up a path string into its elements/folders PathEntry[] splitPath(string path) pure { if( path.startsWith("/") || path.startsWith("\\") ) path = path[1 .. $]; if( path.empty ) return null; if( path.endsWith("/") || path.endsWith("\\") ) path = path[0 .. $-1]; // count the number of path nodes size_t nelements = 0; foreach( i, char ch; path ) if( ch == '\\' || ch == '/' ) nelements++; nelements++; // reserve space for the elements auto elements = new PathEntry[nelements]; size_t eidx = 0; // detect UNC path if(path.startsWith("\\")) { elements[eidx++] = PathEntry(path[0 .. 1]); path = path[1 .. $]; } // read and return the elements size_t startidx = 0; foreach( i, char ch; path ) if( ch == '\\' || ch == '/' ){ elements[eidx++] = PathEntry(path[startidx .. i]); startidx = i+1; } elements[eidx++] = PathEntry(path[startidx .. $]); assert(eidx == nelements); return elements; } unittest { NativePath p; assert(p.toNativeString() == "."); p.endsWithSlash = true; version(Windows) assert(p.toNativeString() == ".\\"); else assert(p.toNativeString() == "./"); p = NativePath("test/"); version(Windows) assert(p.toNativeString() == "test\\"); else assert(p.toNativeString() == "test/"); p.endsWithSlash = false; assert(p.toNativeString() == "test"); } unittest { { auto unc = "\\\\server\\share\\path"; auto uncp = NativePath(unc); uncp.normalize(); version(Windows) assert(uncp.toNativeString() == unc); assert(uncp.absolute); assert(!uncp.endsWithSlash); } { auto abspath = "/test/path/"; auto abspathp = NativePath(abspath); assert(abspathp.toString() == abspath); version(Windows) {} else assert(abspathp.toNativeString() == abspath); assert(abspathp.absolute); assert(abspathp.endsWithSlash); assert(abspathp.length == 2); assert(abspathp[0] == "test"); assert(abspathp[1] == "path"); } { auto relpath = "test/path/"; auto relpathp = NativePath(relpath); assert(relpathp.toString() == relpath); version(Windows) assert(relpathp.toNativeString() == "test\\path\\"); else assert(relpathp.toNativeString() == relpath); assert(!relpathp.absolute); assert(relpathp.endsWithSlash); assert(relpathp.length == 2); assert(relpathp[0] == "test"); assert(relpathp[1] == "path"); } { auto winpath = "C:\\windows\\test"; auto winpathp = NativePath(winpath); version(Windows) { assert(winpathp.toString() == "C:/windows/test", winpathp.toString()); assert(winpathp.toNativeString() == winpath); } else { assert(winpathp.toString() == "/C:/windows/test", winpathp.toString()); assert(winpathp.toNativeString() == "/C:/windows/test"); } assert(winpathp.absolute); assert(!winpathp.endsWithSlash); assert(winpathp.length == 3); assert(winpathp[0] == "C:"); assert(winpathp[1] == "windows"); assert(winpathp[2] == "test"); } { auto dotpath = "/test/../test2/././x/y"; auto dotpathp = NativePath(dotpath); assert(dotpathp.toString() == "/test/../test2/././x/y"); dotpathp.normalize(); assert(dotpathp.toString() == "/test2/x/y"); } { auto dotpath = "/test/..////test2//./x/y"; auto dotpathp = NativePath(dotpath); assert(dotpathp.toString() == "/test/..////test2//./x/y"); dotpathp.normalize(); assert(dotpathp.toString() == "/test2/x/y"); } { auto parentpath = "/path/to/parent"; auto parentpathp = NativePath(parentpath); auto subpath = "/path/to/parent/sub/"; auto subpathp = NativePath(subpath); auto subpath_rel = "sub/"; assert(subpathp.relativeTo(parentpathp).toString() == subpath_rel); auto subfile = "/path/to/parent/child"; auto subfilep = NativePath(subfile); auto subfile_rel = "child"; assert(subfilep.relativeTo(parentpathp).toString() == subfile_rel); } { // relative paths across Windows devices are not allowed version (Windows) { auto p1 = NativePath("\\\\server\\share"); assert(p1.absolute); auto p2 = NativePath("\\\\server\\othershare"); assert(p2.absolute); auto p3 = NativePath("\\\\otherserver\\share"); assert(p3.absolute); auto p4 = NativePath("C:\\somepath"); assert(p4.absolute); auto p5 = NativePath("C:\\someotherpath"); assert(p5.absolute); auto p6 = NativePath("D:\\somepath"); assert(p6.absolute); assert(p4.relativeTo(p5) == NativePath("../somepath")); assert(p4.relativeTo(p6) == NativePath("C:\\somepath")); assert(p4.relativeTo(p1) == NativePath("C:\\somepath")); assert(p1.relativeTo(p2) == NativePath("../share")); assert(p1.relativeTo(p3) == NativePath("\\\\server\\share")); assert(p1.relativeTo(p4) == NativePath("\\\\server\\share")); } } } unittest { assert(NativePath("/foo/bar/baz").relativeTo(NativePath("/foo")).toString == "bar/baz"); assert(NativePath("/foo/bar/baz/").relativeTo(NativePath("/foo")).toString == "bar/baz/"); assert(NativePath("/foo/bar").relativeTo(NativePath("/foo")).toString == "bar"); assert(NativePath("/foo/bar/").relativeTo(NativePath("/foo")).toString == "bar/"); assert(NativePath("/foo").relativeTo(NativePath("/foo/bar")).toString() == ".."); assert(NativePath("/foo/").relativeTo(NativePath("/foo/bar")).toString() == "../"); assert(NativePath("/foo/baz").relativeTo(NativePath("/foo/bar/baz")).toString() == "../../baz"); assert(NativePath("/foo/baz/").relativeTo(NativePath("/foo/bar/baz")).toString() == "../../baz/"); assert(NativePath("/foo/").relativeTo(NativePath("/foo/bar/baz")).toString() == "../../"); assert(NativePath("/foo/").relativeTo(NativePath("/foo/bar/baz/mumpitz")).toString() == "../../../"); assert(NativePath("/foo").relativeTo(NativePath("/foo")).toString() == ""); assert(NativePath("/foo/").relativeTo(NativePath("/foo")).toString() == ""); } dub-1.19.0/source/dub/internal/vibecompat/inet/url.d000066400000000000000000000174331360435400500223110ustar00rootroot00000000000000/** URL parsing routines. Copyright: © 2012 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.internal.vibecompat.inet.url; public import dub.internal.vibecompat.inet.path; version (Have_vibe_d_core) public import vibe.inet.url; else: import std.algorithm; import std.array; import std.conv; import std.exception; import std.string; import std.uri; import std.meta : AliasSeq; /** Represents a URL decomposed into its components. */ struct URL { private { string m_schema; string m_pathString; NativePath m_path; string m_host; ushort m_port; string m_username; string m_password; string m_queryString; string m_anchor; alias m_schemes = AliasSeq!("http", "https", "ftp", "spdy", "file", "sftp"); } /// Constructs a new URL object from its components. this(string schema, string host, ushort port, NativePath path) { m_schema = schema; m_host = host; m_port = port; m_path = path; m_pathString = path.toString(); } /// ditto this(string schema, NativePath path) { this(schema, null, 0, path); } /** Constructs a URL from its string representation. TODO: additional validation required (e.g. valid host and user names and port) */ this(string url_string) { auto str = url_string; enforce(str.length > 0, "Empty URL."); if( str[0] != '/' ){ auto idx = str.countUntil(':'); enforce(idx > 0, "No schema in URL:"~str); m_schema = str[0 .. idx]; str = str[idx+1 .. $]; bool requires_host = false; auto schema_parts = m_schema.split("+"); if (!schema_parts.empty && schema_parts.back.canFind(m_schemes)) { // proto://server/path style enforce(str.startsWith("//"), "URL must start with proto://..."); requires_host = true; str = str[2 .. $]; } auto si = str.countUntil('/'); if( si < 0 ) si = str.length; auto ai = str[0 .. si].countUntil('@'); ptrdiff_t hs = 0; if( ai >= 0 ){ hs = ai+1; auto ci = str[0 .. ai].countUntil(':'); if( ci >= 0 ){ m_username = str[0 .. ci]; m_password = str[ci+1 .. ai]; } else m_username = str[0 .. ai]; enforce(m_username.length > 0, "Empty user name in URL."); } m_host = str[hs .. si]; auto pi = m_host.countUntil(':'); if(pi > 0) { enforce(pi < m_host.length-1, "Empty port in URL."); m_port = to!ushort(m_host[pi+1..$]); m_host = m_host[0 .. pi]; } enforce(!requires_host || m_schema == "file" || m_host.length > 0, "Empty server name in URL."); str = str[si .. $]; } this.localURI = (str == "") ? "/" : str; } /// ditto static URL parse(string url_string) { return URL(url_string); } /// The schema/protocol part of the URL @property string schema() const { return m_schema; } /// ditto @property void schema(string v) { m_schema = v; } /// The path part of the URL in the original string form @property string pathString() const { return m_pathString; } /// The path part of the URL @property NativePath path() const { return m_path; } /// ditto @property void path(NativePath p) { m_path = p; auto pstr = p.toString(); m_pathString = pstr; } /// The host part of the URL (depends on the schema) @property string host() const { return m_host; } /// ditto @property void host(string v) { m_host = v; } /// The port part of the URL (optional) @property ushort port() const { return m_port; } /// ditto @property port(ushort v) { m_port = v; } /// The user name part of the URL (optional) @property string username() const { return m_username; } /// ditto @property void username(string v) { m_username = v; } /// The password part of the URL (optional) @property string password() const { return m_password; } /// ditto @property void password(string v) { m_password = v; } /// The query string part of the URL (optional) @property string queryString() const { return m_queryString; } /// ditto @property void queryString(string v) { m_queryString = v; } /// The anchor part of the URL (optional) @property string anchor() const { return m_anchor; } /// The path part plus query string and anchor @property string localURI() const { auto str = appender!string(); str.reserve(m_pathString.length + 2 + queryString.length + anchor.length); str.put(encode(path.toString())); if( queryString.length ) { str.put("?"); str.put(queryString); } if( anchor.length ) { str.put("#"); str.put(anchor); } return str.data; } /// ditto @property void localURI(string str) { auto ai = str.countUntil('#'); if( ai >= 0 ){ m_anchor = str[ai+1 .. $]; str = str[0 .. ai]; } auto qi = str.countUntil('?'); if( qi >= 0 ){ m_queryString = str[qi+1 .. $]; str = str[0 .. qi]; } m_pathString = str; m_path = NativePath(decode(str)); } /// The URL to the parent path with query string and anchor stripped. @property URL parentURL() const { URL ret; ret.schema = schema; ret.host = host; ret.port = port; ret.username = username; ret.password = password; ret.path = path.parentPath; return ret; } /// Converts this URL object to its string representation. string toString() const { import std.format; auto dst = appender!string(); dst.put(schema); dst.put(":"); auto schema_parts = schema.split("+"); if (!schema_parts.empty && schema_parts.back.canFind(m_schemes)) { dst.put("//"); } dst.put(host); if( m_port > 0 ) formattedWrite(dst, ":%d", m_port); dst.put(localURI); return dst.data; } bool startsWith(const URL rhs) const { if( m_schema != rhs.m_schema ) return false; if( m_host != rhs.m_host ) return false; // FIXME: also consider user, port, querystring, anchor etc return path.startsWith(rhs.m_path); } URL opBinary(string OP)(NativePath rhs) const if( OP == "~" ) { return URL(m_schema, m_host, m_port, m_path ~ rhs); } URL opBinary(string OP)(PathEntry rhs) const if( OP == "~" ) { return URL(m_schema, m_host, m_port, m_path ~ rhs); } void opOpAssign(string OP)(NativePath rhs) if( OP == "~" ) { m_path ~= rhs; } void opOpAssign(string OP)(PathEntry rhs) if( OP == "~" ) { m_path ~= rhs; } /// Tests two URLs for equality using '=='. bool opEquals(ref const URL rhs) const { if( m_schema != rhs.m_schema ) return false; if( m_host != rhs.m_host ) return false; if( m_path != rhs.m_path ) return false; return true; } /// ditto bool opEquals(const URL other) const { return opEquals(other); } int opCmp(ref const URL rhs) const { if( m_schema != rhs.m_schema ) return m_schema.cmp(rhs.m_schema); if( m_host != rhs.m_host ) return m_host.cmp(rhs.m_host); if( m_path != rhs.m_path ) return m_path.opCmp(rhs.m_path); return true; } } unittest { auto url = URL.parse("https://www.example.net/index.html"); assert(url.schema == "https", url.schema); assert(url.host == "www.example.net", url.host); assert(url.path == NativePath("/index.html"), url.path.toString()); url = URL.parse("http://jo.doe:password@sub.www.example.net:4711/sub2/index.html?query#anchor"); assert(url.schema == "http", url.schema); assert(url.username == "jo.doe", url.username); assert(url.password == "password", url.password); assert(url.port == 4711, to!string(url.port)); assert(url.host == "sub.www.example.net", url.host); assert(url.path.toString() == "/sub2/index.html", url.path.toString()); assert(url.queryString == "query", url.queryString); assert(url.anchor == "anchor", url.anchor); url = URL("http://localhost")~NativePath("packages"); assert(url.toString() == "http://localhost/packages", url.toString()); url = URL("http://localhost/")~NativePath("packages"); assert(url.toString() == "http://localhost/packages", url.toString()); url = URL.parse("dub+https://code.dlang.org/"); assert(url.host == "code.dlang.org"); assert(url.toString() == "dub+https://code.dlang.org/"); assert(url.schema == "dub+https"); } dub-1.19.0/source/dub/package_.d000066400000000000000000000613571360435400500163410ustar00rootroot00000000000000/** Contains high-level functionality for working with packages. Copyright: © 2012-2013 Matthias Dondorff, © 2012-2016 Sönke Ludwig License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Matthias Dondorff, Sönke Ludwig, Martin Nowak, Nick Sabalausky */ module dub.package_; public import dub.recipe.packagerecipe; import dub.compilers.compiler; import dub.dependency; import dub.description; import dub.recipe.json; import dub.recipe.sdl; import dub.internal.utils; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.url; import std.algorithm; import std.array; import std.conv; import std.exception; import std.file; import std.range; import std.string; import std.typecons : Nullable; /// Lists the supported package recipe formats. enum PackageFormat { json, /// JSON based, using the ".json" file extension sdl /// SDLang based, using the ".sdl" file extension } struct FilenameAndFormat { string filename; PackageFormat format; } /// Supported package descriptions in decreasing order of preference. static immutable FilenameAndFormat[] packageInfoFiles = [ {"dub.json", PackageFormat.json}, {"dub.sdl", PackageFormat.sdl}, {"package.json", PackageFormat.json} ]; /// Returns a list of all recognized package recipe file names in descending order of precedence. @property string[] packageInfoFilenames() { return packageInfoFiles.map!(f => cast(string)f.filename).array; } /// Returns the default package recile file name. @property string defaultPackageFilename() { return packageInfoFiles[0].filename; } /** Represents a package, including its sub packages. */ class Package { private { NativePath m_path; NativePath m_infoFile; PackageRecipe m_info; PackageRecipe m_rawRecipe; Package m_parentPackage; } /** Constructs a `Package` using an in-memory package recipe. Params: json_recipe = The package recipe in JSON format recipe = The package recipe in generic format root = The directory in which the package resides (if any). parent = Reference to the parent package, if the new package is a sub package. version_override = Optional version to associate to the package instead of the one declared in the package recipe, or the one determined by invoking the VCS (GIT currently). */ this(Json json_recipe, NativePath root = NativePath(), Package parent = null, string version_override = "") { import dub.recipe.json; PackageRecipe recipe; parseJson(recipe, json_recipe, parent ? parent.name : null); this(recipe, root, parent, version_override); } /// ditto this(PackageRecipe recipe, NativePath root = NativePath(), Package parent = null, string version_override = "") { // save the original recipe m_rawRecipe = recipe.clone; if (!version_override.empty) recipe.version_ = version_override; // try to run git to determine the version of the package if no explicit version was given if (recipe.version_.length == 0 && !parent) { try recipe.version_ = determineVersionFromSCM(root); catch (Exception e) logDebug("Failed to determine version by SCM: %s", e.msg); if (recipe.version_.length == 0) { logDiagnostic("Note: Failed to determine version of package %s at %s. Assuming ~master.", recipe.name, this.path.toNativeString()); // TODO: Assume unknown version here? // recipe.version_ = Version.unknown.toString(); recipe.version_ = Version.masterBranch.toString(); } else logDiagnostic("Determined package version using GIT: %s %s", recipe.name, recipe.version_); } m_parentPackage = parent; m_path = root; m_path.endsWithSlash = true; // use the given recipe as the basis m_info = recipe; checkDubRequirements(); fillWithDefaults(); } /** Searches the given directory for package recipe files. Params: directory = The directory to search Returns: Returns the full path to the package file, if any was found. Otherwise returns an empty path. */ static NativePath findPackageFile(NativePath directory) { foreach (file; packageInfoFiles) { auto filename = directory ~ file.filename; if (existsFile(filename)) return filename; } return NativePath.init; } /** Constructs a `Package` using a package that is physically present on the local file system. Params: root = The directory in which the package resides. recipe_file = Optional path to the package recipe file. If left empty, the `root` directory will be searched for a recipe file. parent = Reference to the parent package, if the new package is a sub package. version_override = Optional version to associate to the package instead of the one declared in the package recipe, or the one determined by invoking the VCS (GIT currently). */ static Package load(NativePath root, NativePath recipe_file = NativePath.init, Package parent = null, string version_override = "") { import dub.recipe.io; if (recipe_file.empty) recipe_file = findPackageFile(root); enforce(!recipe_file.empty, "No package file found in %s, expected one of %s" .format(root.toNativeString(), packageInfoFiles.map!(f => cast(string)f.filename).join("/"))); auto recipe = readPackageRecipe(recipe_file, parent ? parent.name : null); auto ret = new Package(recipe, root, parent, version_override); ret.m_infoFile = recipe_file; return ret; } /** Returns the qualified name of the package. The qualified name includes any possible parent package if this package is a sub package. */ @property string name() const { if (m_parentPackage) return m_parentPackage.name ~ ":" ~ m_info.name; else return m_info.name; } /** Returns the directory in which the package resides. Note that this can be empty for packages that are not stored in the local file system. */ @property NativePath path() const { return m_path; } /** Accesses the version associated with this package. Note that this is a shortcut to `this.recipe.version_`. */ @property Version version_() const { return m_parentPackage ? m_parentPackage.version_ : Version(m_info.version_); } /// ditto @property void version_(Version value) { assert(m_parentPackage is null); m_info.version_ = value.toString(); } /** Accesses the recipe contents of this package. The recipe contains any default values and configurations added by DUB. To access the raw user recipe, use the `rawRecipe` property. See_Also: `rawRecipe` */ @property ref inout(PackageRecipe) recipe() inout { return m_info; } /** Accesses the original package recipe. The returned recipe matches exactly the contents of the original package recipe. For the effective package recipe, augmented with DUB generated default settings and configurations, use the `recipe` property. See_Also: `recipe` */ @property ref const(PackageRecipe) rawRecipe() const { return m_rawRecipe; } /** Returns the path to the package recipe file. Note that this can be empty for packages that are not stored in the local file system. */ @property NativePath recipePath() const { return m_infoFile; } /** Returns the base package of this package. The base package is the root of the sub package hierarchy (i.e. the topmost parent). This will be `null` for packages that are not sub packages. */ @property inout(Package) basePackage() inout { return m_parentPackage ? m_parentPackage.basePackage : this; } /** Returns the parent of this package. The parent package is the package that contains a sub package. This will be `null` for packages that are not sub packages. */ @property inout(Package) parentPackage() inout { return m_parentPackage; } /** Returns the list of all sub packages. Note that this is a shortcut for `this.recipe.subPackages`. */ @property inout(SubPackage)[] subPackages() inout { return m_info.subPackages; } /** Returns the list of all build configuration names. Configuration contents can be accessed using `this.recipe.configurations`. */ @property string[] configurations() const { auto ret = appender!(string[])(); foreach (ref config; m_info.configurations) ret.put(config.name); return ret.data; } /** Writes the current recipe contents to a recipe file. The parameter-less overload writes to `this.path`, which must not be empty. The default recipe file name will be used in this case. */ void storeInfo() { storeInfo(m_path); m_infoFile = m_path ~ defaultPackageFilename; } /// ditto void storeInfo(NativePath path) const { enforce(!version_.isUnknown, "Trying to store a package with an 'unknown' version, this is not supported."); auto filename = path ~ defaultPackageFilename; auto dstFile = openFile(filename.toNativeString(), FileMode.createTrunc); scope(exit) dstFile.close(); dstFile.writePrettyJsonString(m_info.toJson()); } /// Get the metadata cache for this package @property Json metadataCache() { enum silent_fail = true; return jsonFromFile(m_path ~ ".dub/metadata_cache.json", silent_fail); } /// Write metadata cache for this package @property void metadataCache(Json json) { enum create_if_missing = true; if (isWritableDir(m_path ~ ".dub", create_if_missing)) writeJsonFile(m_path ~ ".dub/metadata_cache.json", json); // TODO: store elsewhere } /** Returns the package recipe of a non-path-based sub package. For sub packages that are declared within the package recipe of the parent package, this function will return the corresponding recipe. Sub packages declared using a path must be loaded manually (or using the `PackageManager`). */ Nullable!PackageRecipe getInternalSubPackage(string name) { foreach (ref p; m_info.subPackages) if (p.path.empty && p.recipe.name == name) return Nullable!PackageRecipe(p.recipe); return Nullable!PackageRecipe(); } /** Searches for use of compiler-specific flags that have generic alternatives. This will output a warning message for each such flag to the console. */ void warnOnSpecialCompilerFlags() { // warn about use of special flags m_info.buildSettings.warnOnSpecialCompilerFlags(m_info.name, null); foreach (ref config; m_info.configurations) config.buildSettings.warnOnSpecialCompilerFlags(m_info.name, config.name); } /** Retrieves a build settings template. If no `config` is given, this returns the build settings declared at the root level of the package recipe. Otherwise returns the settings declared within the given configuration (excluding those at the root level). Note that this is a shortcut to accessing `this.recipe.buildSettings` or `this.recipe.configurations[].buildSettings`. */ const(BuildSettingsTemplate) getBuildSettings(string config = null) const { if (config.length) { foreach (ref conf; m_info.configurations) if (conf.name == config) return conf.buildSettings; assert(false, "Unknown configuration: "~config); } else { return m_info.buildSettings; } } /** Returns all BuildSettings for the given platform and configuration. This will gather the effective build settings declared in tha package recipe for when building on a particular platform and configuration. Root build settings and configuration specific settings will be merged. */ BuildSettings getBuildSettings(in BuildPlatform platform, string config) const { BuildSettings ret; m_info.buildSettings.getPlatformSettings(ret, platform, this.path); bool found = false; foreach(ref conf; m_info.configurations){ if( conf.name != config ) continue; conf.buildSettings.getPlatformSettings(ret, platform, this.path); found = true; break; } assert(found || config is null, "Unknown configuration for "~m_info.name~": "~config); // construct default target name based on package name if( ret.targetName.empty ) ret.targetName = this.name.replace(":", "_"); // special support for DMD style flags getCompiler("dmd").extractBuildOptions(ret); return ret; } /** Returns the combination of all build settings for all configurations and platforms. This can be useful for IDEs to gather a list of all potentially used files or settings. */ BuildSettings getCombinedBuildSettings() const { BuildSettings ret; m_info.buildSettings.getPlatformSettings(ret, BuildPlatform.any, this.path); foreach(ref conf; m_info.configurations) conf.buildSettings.getPlatformSettings(ret, BuildPlatform.any, this.path); // construct default target name based on package name if (ret.targetName.empty) ret.targetName = this.name.replace(":", "_"); // special support for DMD style flags getCompiler("dmd").extractBuildOptions(ret); return ret; } /** Adds build type specific settings to an existing set of build settings. This function searches the package recipe for overridden build types. If none is found, the default build settings will be applied, if `build_type` matches a default build type name. An exception is thrown otherwise. */ void addBuildTypeSettings(ref BuildSettings settings, in BuildPlatform platform, string build_type) const { if (build_type == "$DFLAGS") { import std.process; string dflags = environment.get("DFLAGS"); settings.addDFlags(dflags.split()); return; } if (auto pbt = build_type in m_info.buildTypes) { logDiagnostic("Using custom build type '%s'.", build_type); pbt.getPlatformSettings(settings, platform, this.path); } else { with(BuildOption) switch (build_type) { default: throw new Exception(format("Unknown build type for %s: '%s'", this.name, build_type)); case "plain": break; case "debug": settings.addOptions(debugMode, debugInfo); break; case "release": settings.addOptions(releaseMode, optimize, inline); break; case "release-debug": settings.addOptions(releaseMode, optimize, inline, debugInfo); break; case "release-nobounds": settings.addOptions(releaseMode, optimize, inline, noBoundsCheck); break; case "unittest": settings.addOptions(unittests, debugMode, debugInfo); break; case "docs": settings.addOptions(syntaxOnly, _docs); break; case "ddox": settings.addOptions(syntaxOnly, _ddox); break; case "profile": settings.addOptions(profile, optimize, inline, debugInfo); break; case "profile-gc": settings.addOptions(profileGC, debugInfo); break; case "cov": settings.addOptions(coverage, debugInfo); break; case "unittest-cov": settings.addOptions(unittests, coverage, debugMode, debugInfo); break; case "syntax": settings.addOptions(syntaxOnly); break; } } } /** Returns the selected configuration for a certain dependency. If no configuration is specified in the package recipe, null will be returned instead. FIXME: The `platform` parameter is currently ignored, as the `"subConfigurations"` field doesn't support platform suffixes. */ string getSubConfiguration(string config, in Package dependency, in BuildPlatform platform) const { bool found = false; foreach(ref c; m_info.configurations){ if( c.name == config ){ if( auto pv = dependency.name in c.buildSettings.subConfigurations ) return *pv; found = true; break; } } assert(found || config is null, "Invalid configuration \""~config~"\" for "~this.name); if( auto pv = dependency.name in m_info.buildSettings.subConfigurations ) return *pv; return null; } /** Returns the default configuration to build for the given platform. This will return the first configuration that is applicable to the given platform, or `null` if none is applicable. By default, only library configurations will be returned. Setting `allow_non_library` to `true` will also return executable configurations. See_Also: `getPlatformConfigurations` */ string getDefaultConfiguration(in BuildPlatform platform, bool allow_non_library = false) const { foreach (ref conf; m_info.configurations) { if (!conf.matchesPlatform(platform)) continue; if (!allow_non_library && conf.buildSettings.targetType == TargetType.executable) continue; return conf.name; } return null; } /** Returns a list of configurations suitable for the given platform. Params: platform = The platform against which to match configurations allow_non_library = If set to true, executable configurations will also be included. See_Also: `getDefaultConfiguration` */ string[] getPlatformConfigurations(in BuildPlatform platform, bool allow_non_library = false) const { auto ret = appender!(string[]); foreach(ref conf; m_info.configurations){ if (!conf.matchesPlatform(platform)) continue; if (!allow_non_library && conf.buildSettings.targetType == TargetType.executable) continue; ret ~= conf.name; } if (ret.data.length == 0) ret.put(null); return ret.data; } /** Determines if the package has a dependency to a certain package. Params: dependency_name = The name of the package to search for config = Name of the configuration to use when searching for dependencies See_Also: `getDependencies` */ bool hasDependency(string dependency_name, string config) const { if (dependency_name in m_info.buildSettings.dependencies) return true; foreach (ref c; m_info.configurations) if ((config.empty || c.name == config) && dependency_name in c.buildSettings.dependencies) return true; return false; } /** Retrieves all dependencies for a particular configuration. This includes dependencies that are declared at the root level of the package recipe, as well as those declared within the specified configuration. If no configuration with the given name exists, only dependencies declared at the root level will be returned. See_Also: `hasDependency` */ const(Dependency[string]) getDependencies(string config) const { Dependency[string] ret; foreach (k, v; m_info.buildSettings.dependencies) ret[k] = v; foreach (ref conf; m_info.configurations) if (conf.name == config) { foreach (k, v; conf.buildSettings.dependencies) ret[k] = v; break; } return ret; } /** Returns a list of all possible dependencies of the package. This list includes all dependencies of all configurations. The same package may occur multiple times with possibly different `Dependency` values. */ PackageDependency[] getAllDependencies() const { auto ret = appender!(PackageDependency[]); getAllDependenciesRange().copy(ret); return ret.data; } // Left as package until the final API for this has been found package auto getAllDependenciesRange() const { return chain( only(this.recipe.buildSettings.dependencies.byKeyValue), this.recipe.configurations.map!(c => c.buildSettings.dependencies.byKeyValue) ) .joiner() .map!(d => PackageDependency(d.key, d.value)); } /** Returns a description of the package for use in IDEs or build tools. */ PackageDescription describe(BuildPlatform platform, string config) const { return describe(platform, getCompiler(platform.compilerBinary), config); } /// ditto PackageDescription describe(BuildPlatform platform, Compiler compiler, string config) const { PackageDescription ret; ret.configuration = config; ret.path = m_path.toNativeString(); ret.name = this.name; ret.version_ = this.version_; ret.description = m_info.description; ret.homepage = m_info.homepage; ret.authors = m_info.authors.dup; ret.copyright = m_info.copyright; ret.license = m_info.license; ret.dependencies = getDependencies(config).keys; // save build settings BuildSettings bs = getBuildSettings(platform, config); BuildSettings allbs = getCombinedBuildSettings(); ret.targetType = bs.targetType; ret.targetPath = bs.targetPath; ret.targetName = bs.targetName; if (ret.targetType != TargetType.none && compiler) ret.targetFileName = compiler.getTargetFileName(bs, platform); ret.workingDirectory = bs.workingDirectory; ret.mainSourceFile = bs.mainSourceFile; ret.dflags = bs.dflags; ret.lflags = bs.lflags; ret.libs = bs.libs; ret.copyFiles = bs.copyFiles; ret.versions = bs.versions; ret.debugVersions = bs.debugVersions; ret.importPaths = bs.importPaths; ret.stringImportPaths = bs.stringImportPaths; ret.preGenerateCommands = bs.preGenerateCommands; ret.postGenerateCommands = bs.postGenerateCommands; ret.preBuildCommands = bs.preBuildCommands; ret.postBuildCommands = bs.postBuildCommands; // prettify build requirements output for (int i = 1; i <= BuildRequirement.max; i <<= 1) if (bs.requirements & cast(BuildRequirement)i) ret.buildRequirements ~= cast(BuildRequirement)i; // prettify options output for (int i = 1; i <= BuildOption.max; i <<= 1) if (bs.options & cast(BuildOption)i) ret.options ~= cast(BuildOption)i; // collect all possible source files and determine their types SourceFileRole[string] sourceFileTypes; foreach (f; allbs.stringImportFiles) sourceFileTypes[f] = SourceFileRole.unusedStringImport; foreach (f; allbs.importFiles) sourceFileTypes[f] = SourceFileRole.unusedImport; foreach (f; allbs.sourceFiles) sourceFileTypes[f] = SourceFileRole.unusedSource; foreach (f; bs.stringImportFiles) sourceFileTypes[f] = SourceFileRole.stringImport; foreach (f; bs.importFiles) sourceFileTypes[f] = SourceFileRole.import_; foreach (f; bs.sourceFiles) sourceFileTypes[f] = SourceFileRole.source; foreach (f; sourceFileTypes.byKey.array.sort()) { SourceFileDescription sf; sf.path = f; sf.role = sourceFileTypes[f]; ret.files ~= sf; } return ret; } private void checkDubRequirements() { import dub.dependency : Dependency; import dub.semver : isValidVersion; import dub.version_ : dubVersion; import std.exception : enforce; const dep = m_info.toolchainRequirements.dub; static assert(dubVersion.length); static if (dubVersion[0] == 'v') { enum dv = dubVersion[1 .. $]; } else { enum dv = dubVersion; } static assert(isValidVersion(dv)); enforce(dep.matches(dv), "dub-" ~ dv ~ " does not comply with toolchainRequirements.dub " ~ "specification: " ~ m_info.toolchainRequirements.dub.toString() ~ "\nPlease consider upgrading your DUB installation"); } private void fillWithDefaults() { auto bs = &m_info.buildSettings; // check for default string import folders if ("" !in bs.stringImportPaths) { foreach(defvf; ["views"]){ if( existsFile(m_path ~ defvf) ) bs.stringImportPaths[""] ~= defvf; } } // check for default source folders immutable hasSP = ("" in bs.sourcePaths) !is null; immutable hasIP = ("" in bs.importPaths) !is null; if (!hasSP || !hasIP) { foreach (defsf; ["source/", "src/"]) { if (existsFile(m_path ~ defsf)) { if (!hasSP) bs.sourcePaths[""] ~= defsf; if (!hasIP) bs.importPaths[""] ~= defsf; } } } // check for default app_main string app_main_file; auto pkg_name = m_info.name.length ? m_info.name : "unknown"; foreach(sf; bs.sourcePaths.get("", null)){ auto p = m_path ~ sf; if( !existsFile(p) ) continue; foreach(fil; ["app.d", "main.d", pkg_name ~ "/main.d", pkg_name ~ "/" ~ "app.d"]){ if( existsFile(p ~ fil) ) { app_main_file = (NativePath(sf) ~ fil).toNativeString(); break; } } } // generate default configurations if none are defined if (m_info.configurations.length == 0) { if (bs.targetType == TargetType.executable) { BuildSettingsTemplate app_settings; app_settings.targetType = TargetType.executable; if (bs.mainSourceFile.empty) app_settings.mainSourceFile = app_main_file; m_info.configurations ~= ConfigurationInfo("application", app_settings); } else if (bs.targetType != TargetType.none) { BuildSettingsTemplate lib_settings; lib_settings.targetType = bs.targetType == TargetType.autodetect ? TargetType.library : bs.targetType; if (bs.targetType == TargetType.autodetect) { if (app_main_file.length) { lib_settings.excludedSourceFiles[""] ~= app_main_file; BuildSettingsTemplate app_settings; app_settings.targetType = TargetType.executable; app_settings.mainSourceFile = app_main_file; m_info.configurations ~= ConfigurationInfo("application", app_settings); } } m_info.configurations ~= ConfigurationInfo("library", lib_settings); } } } package void simpleLint() const { if (m_parentPackage) { if (m_parentPackage.path != path) { if (this.recipe.license.length && this.recipe.license != m_parentPackage.recipe.license) logWarn("Warning: License in subpackage %s is different than it's parent package, this is discouraged.", name); } } if (name.empty) logWarn("Warning: The package in %s has no name.", path); bool[string] cnames; foreach (ref c; this.recipe.configurations) { if (c.name in cnames) logWarn("Warning: Multiple configurations with the name \"%s\" are defined in package \"%s\". This will most likely cause configuration resolution issues.", c.name, this.name); cnames[c.name] = true; } } } private string determineVersionFromSCM(NativePath path) { if (existsFile(path ~ ".git")) { import dub.internal.git : determineVersionWithGit; return determineVersionWithGit(path); } return null; } dub-1.19.0/source/dub/packagemanager.d000066400000000000000000000626151360435400500175330ustar00rootroot00000000000000/** Management of packages on the local computer. Copyright: © 2012-2016 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig, Matthias Dondorff */ module dub.packagemanager; import dub.dependency; import dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; import dub.package_; import std.algorithm : countUntil, filter, sort, canFind, remove; import std.array; import std.conv; import std.digest.sha; import std.encoding : sanitize; import std.exception; import std.file; import std.string; import std.zip; /// The PackageManager can retrieve present packages and get / remove /// packages. class PackageManager { private { Repository[] m_repositories; NativePath[] m_searchPath; Package[] m_packages; Package[] m_temporaryPackages; bool m_disableDefaultSearchPaths = false; } this(NativePath user_path, NativePath system_path, bool refresh_packages = true) { m_repositories = [ Repository(user_path ~ "packages/"), Repository(system_path ~ "packages/")]; if (refresh_packages) refresh(true); } this(NativePath package_path, NativePath user_path, NativePath system_path, bool refresh_packages = true) { m_repositories = [ Repository(package_path ~ ".dub/packages/"), Repository(user_path ~ "packages/"), Repository(system_path ~ "packages/")]; if (refresh_packages) refresh(true); } /** Gets/sets the list of paths to search for local packages. */ @property void searchPath(NativePath[] paths) { if (paths == m_searchPath) return; m_searchPath = paths.dup; refresh(false); } /// ditto @property const(NativePath)[] searchPath() const { return m_searchPath; } /** Disables searching DUB's predefined search paths. */ @property void disableDefaultSearchPaths(bool val) { if (val == m_disableDefaultSearchPaths) return; m_disableDefaultSearchPaths = val; refresh(true); } /** Returns the effective list of search paths, including default ones. */ @property const(NativePath)[] completeSearchPath() const { auto ret = appender!(NativePath[])(); ret.put(cast(NativePath[])m_searchPath); // work around Phobos 17251 if (!m_disableDefaultSearchPaths) { foreach (ref repo; m_repositories) { ret.put(cast(NativePath[])repo.searchPath); ret.put(cast(NativePath)repo.packagePath); } } return ret.data; } /** Sets additional (read-only) package cache paths to search for packages. Cache paths have the same structure as the default cache paths, such as ".dub/packages/". Note that previously set custom paths will be removed when setting this property. */ @property void customCachePaths(NativePath[] custom_cache_paths) { import std.algorithm.iteration : map; import std.array : array; m_repositories.length = LocalPackageType.max+1; m_repositories ~= custom_cache_paths.map!(p => Repository(p)).array; refresh(false); } /** Looks up a specific package. Looks up a package matching the given version/path in the set of registered packages. The lookup order is done according the the usual rules (see getPackageIterator). Params: name = The name of the package ver = The exact version of the package to query path = An exact path that the package must reside in. Note that the package must still be registered in the package manager. enable_overrides = Apply the local package override list before returning a package (enabled by default) Returns: The matching package or null if no match was found. */ Package getPackage(string name, Version ver, bool enable_overrides = true) { if (enable_overrides) { foreach (ref repo; m_repositories) foreach (ovr; repo.overrides) if (ovr.package_ == name && ovr.version_.matches(ver)) { Package pack; if (!ovr.targetPath.empty) pack = getOrLoadPackage(ovr.targetPath); else pack = getPackage(name, ovr.targetVersion, false); if (pack) return pack; logWarn("Package override %s %s -> %s %s doesn't reference an existing package.", ovr.package_, ovr.version_, ovr.targetVersion, ovr.targetPath); } } foreach (p; getPackageIterator(name)) if (p.version_ == ver) return p; return null; } /// ditto Package getPackage(string name, string ver, bool enable_overrides = true) { return getPackage(name, Version(ver), enable_overrides); } /// ditto Package getPackage(string name, Version ver, NativePath path) { auto ret = getPackage(name, path); if (!ret || ret.version_ != ver) return null; return ret; } /// ditto Package getPackage(string name, string ver, NativePath path) { return getPackage(name, Version(ver), path); } /// ditto Package getPackage(string name, NativePath path) { foreach( p; getPackageIterator(name) ) if (p.path.startsWith(path)) return p; return null; } /** Looks up the first package matching the given name. */ Package getFirstPackage(string name) { foreach (ep; getPackageIterator(name)) return ep; return null; } /** For a given package path, returns the corresponding package. If the package is already loaded, a reference is returned. Otherwise the package gets loaded and cached for the next call to this function. Params: path = NativePath to the root directory of the package recipe_path = Optional path to the recipe file of the package allow_sub_packages = Also return a sub package if it resides in the given folder Returns: The packages loaded from the given path Throws: Throws an exception if no package can be loaded */ Package getOrLoadPackage(NativePath path, NativePath recipe_path = NativePath.init, bool allow_sub_packages = false) { path.endsWithSlash = true; foreach (p; getPackageIterator()) if (p.path == path && (!p.parentPackage || (allow_sub_packages && p.parentPackage.path != p.path))) return p; auto pack = Package.load(path, recipe_path); addPackages(m_temporaryPackages, pack); return pack; } /** Searches for the latest version of a package matching the given dependency. */ Package getBestPackage(string name, Dependency version_spec, bool enable_overrides = true) { Package ret; foreach (p; getPackageIterator(name)) if (version_spec.matches(p.version_) && (!ret || p.version_ > ret.version_)) ret = p; if (enable_overrides && ret) { if (auto ovr = getPackage(name, ret.version_)) return ovr; } return ret; } /// ditto Package getBestPackage(string name, string version_spec) { return getBestPackage(name, Dependency(version_spec)); } /** Gets the a specific sub package. In contrast to `Package.getSubPackage`, this function supports path based sub packages. Params: base_package = The package from which to get a sub package sub_name = Name of the sub package (not prefixed with the base package name) silent_fail = If set to true, the function will return `null` if no package is found. Otherwise will throw an exception. */ Package getSubPackage(Package base_package, string sub_name, bool silent_fail) { foreach (p; getPackageIterator(base_package.name~":"~sub_name)) if (p.parentPackage is base_package) return p; enforce(silent_fail, "Sub package \""~base_package.name~":"~sub_name~"\" doesn't exist."); return null; } /** Determines if a package is managed by DUB. Managed packages can be upgraded and removed. */ bool isManagedPackage(Package pack) const { auto ppath = pack.basePackage.path; return isManagedPath(ppath); } /** Determines if a specific path is within a DUB managed package folder. By default, managed folders are "~/.dub/packages" and "/var/lib/dub/packages". */ bool isManagedPath(NativePath path) const { foreach (rep; m_repositories) { NativePath rpath = rep.packagePath; if (path.startsWith(rpath)) return true; } return false; } /** Enables iteration over all known local packages. Returns: A delegate suitable for use with `foreach` is returned. */ int delegate(int delegate(ref Package)) getPackageIterator() { int iterator(int delegate(ref Package) del) { foreach (tp; m_temporaryPackages) if (auto ret = del(tp)) return ret; // first search local packages foreach (ref repo; m_repositories) foreach (p; repo.localPackages) if (auto ret = del(p)) return ret; // and then all packages gathered from the search path foreach( p; m_packages ) if( auto ret = del(p) ) return ret; return 0; } return &iterator; } /** Enables iteration over all known local packages with a certain name. Returns: A delegate suitable for use with `foreach` is returned. */ int delegate(int delegate(ref Package)) getPackageIterator(string name) { int iterator(int delegate(ref Package) del) { foreach (p; getPackageIterator()) if (p.name == name) if (auto ret = del(p)) return ret; return 0; } return &iterator; } /** Returns a list of all package overrides for the given scope. */ const(PackageOverride)[] getOverrides(LocalPackageType scope_) const { return m_repositories[scope_].overrides; } /** Adds a new override for the given package. */ void addOverride(LocalPackageType scope_, string package_, Dependency version_spec, Version target) { m_repositories[scope_].overrides ~= PackageOverride(package_, version_spec, target); writeLocalPackageOverridesFile(scope_); } /// ditto void addOverride(LocalPackageType scope_, string package_, Dependency version_spec, NativePath target) { m_repositories[scope_].overrides ~= PackageOverride(package_, version_spec, target); writeLocalPackageOverridesFile(scope_); } /** Removes an existing package override. */ void removeOverride(LocalPackageType scope_, string package_, Dependency version_spec) { Repository* rep = &m_repositories[scope_]; foreach (i, ovr; rep.overrides) { if (ovr.package_ != package_ || ovr.version_ != version_spec) continue; rep.overrides = rep.overrides[0 .. i] ~ rep.overrides[i+1 .. $]; writeLocalPackageOverridesFile(scope_); return; } throw new Exception(format("No override exists for %s %s", package_, version_spec)); } /// Extracts the package supplied as a path to it's zip file to the /// destination and sets a version field in the package description. Package storeFetchedPackage(NativePath zip_file_path, Json package_info, NativePath destination) { import std.range : walkLength; auto package_name = package_info["name"].get!string; auto package_version = package_info["version"].get!string; logDebug("Placing package '%s' version '%s' to location '%s' from file '%s'", package_name, package_version, destination.toNativeString(), zip_file_path.toNativeString()); if( existsFile(destination) ){ throw new Exception(format("%s (%s) needs to be removed from '%s' prior placement.", package_name, package_version, destination)); } // open zip file ZipArchive archive; { logDebug("Opening file %s", zip_file_path); auto f = openFile(zip_file_path, FileMode.read); scope(exit) f.close(); archive = new ZipArchive(f.readAll()); } logDebug("Extracting from zip."); // In a github zip, the actual contents are in a subfolder alias PSegment = typeof(NativePath.init.head); PSegment[] zip_prefix; outer: foreach(ArchiveMember am; archive.directory) { auto path = NativePath(am.name).bySegment.array; foreach (fil; packageInfoFiles) if (path.length == 2 && path[$-1].name == fil.filename) { zip_prefix = path[0 .. $-1]; break outer; } } logDebug("zip root folder: %s", zip_prefix); NativePath getCleanedPath(string fileName) { auto path = NativePath(fileName); if (zip_prefix.length && !path.bySegment.startsWith(zip_prefix)) return NativePath.init; static if (is(typeof(path[0 .. 1]))) return path[zip_prefix.length .. $]; else return NativePath(path.bySegment.array[zip_prefix.length .. $]); } static void setAttributes(string path, ArchiveMember am) { import std.datetime : DosFileTimeToSysTime; auto mtime = DosFileTimeToSysTime(am.time); setTimes(path, mtime, mtime); if (auto attrs = am.fileAttributes) std.file.setAttributes(path, attrs); } // extract & place mkdirRecurse(destination.toNativeString()); logDebug("Copying all files..."); int countFiles = 0; foreach(ArchiveMember a; archive.directory) { auto cleanedPath = getCleanedPath(a.name); if(cleanedPath.empty) continue; auto dst_path = destination ~ cleanedPath; logDebug("Creating %s", cleanedPath); if( dst_path.endsWithSlash ){ if( !existsDirectory(dst_path) ) mkdirRecurse(dst_path.toNativeString()); } else { if( !existsDirectory(dst_path.parentPath) ) mkdirRecurse(dst_path.parentPath.toNativeString()); { auto dstFile = openFile(dst_path, FileMode.createTrunc); scope(exit) dstFile.close(); dstFile.put(archive.expand(a)); } setAttributes(dst_path.toNativeString(), a); ++countFiles; } } logDebug("%s file(s) copied.", to!string(countFiles)); // overwrite dub.json (this one includes a version field) auto pack = Package.load(destination, NativePath.init, null, package_info["version"].get!string); if (pack.recipePath.head != defaultPackageFilename) // Storeinfo saved a default file, this could be different to the file from the zip. removeFile(pack.recipePath); pack.storeInfo(); addPackages(m_packages, pack); return pack; } /// Removes the given the package. void remove(in Package pack) { logDebug("Remove %s, version %s, path '%s'", pack.name, pack.version_, pack.path); enforce(!pack.path.empty, "Cannot remove package "~pack.name~" without a path."); // remove package from repositories' list bool found = false; bool removeFrom(Package[] packs, in Package pack) { auto packPos = countUntil!("a.path == b.path")(packs, pack); if(packPos != -1) { packs = .remove(packs, packPos); return true; } return false; } foreach(repo; m_repositories) { if(removeFrom(repo.localPackages, pack)) { found = true; break; } } if(!found) found = removeFrom(m_packages, pack); enforce(found, "Cannot remove, package not found: '"~ pack.name ~"', path: " ~ to!string(pack.path)); logDebug("About to delete root folder for package '%s'.", pack.path); rmdirRecurse(pack.path.toNativeString()); logInfo("Removed package: '"~pack.name~"'"); } /// Compatibility overload. Use the version without a `force_remove` argument instead. void remove(in Package pack, bool force_remove) { remove(pack); } Package addLocalPackage(NativePath path, string verName, LocalPackageType type) { path.endsWithSlash = true; auto pack = Package.load(path); enforce(pack.name.length, "The package has no name, defined in: " ~ path.toString()); if (verName.length) pack.version_ = Version(verName); // don't double-add packages Package[]* packs = &m_repositories[type].localPackages; foreach (p; *packs) { if (p.path == path) { enforce(p.version_ == pack.version_, "Adding the same local package twice with differing versions is not allowed."); logInfo("Package is already registered: %s (version: %s)", p.name, p.version_); return p; } } addPackages(*packs, pack); writeLocalPackageList(type); logInfo("Registered package: %s (version: %s)", pack.name, pack.version_); return pack; } void removeLocalPackage(NativePath path, LocalPackageType type) { path.endsWithSlash = true; Package[]* packs = &m_repositories[type].localPackages; size_t[] to_remove; foreach( i, entry; *packs ) if( entry.path == path ) to_remove ~= i; enforce(to_remove.length > 0, "No "~type.to!string()~" package found at "~path.toNativeString()); string[Version] removed; foreach_reverse( i; to_remove ) { removed[(*packs)[i].version_] = (*packs)[i].name; *packs = (*packs)[0 .. i] ~ (*packs)[i+1 .. $]; } writeLocalPackageList(type); foreach(ver, name; removed) logInfo("Deregistered package: %s (version: %s)", name, ver); } /// For the given type add another path where packages will be looked up. void addSearchPath(NativePath path, LocalPackageType type) { m_repositories[type].searchPath ~= path; writeLocalPackageList(type); } /// Removes a search path from the given type. void removeSearchPath(NativePath path, LocalPackageType type) { m_repositories[type].searchPath = m_repositories[type].searchPath.filter!(p => p != path)().array(); writeLocalPackageList(type); } void refresh(bool refresh_existing_packages) { logDiagnostic("Refreshing local packages (refresh existing: %s)...", refresh_existing_packages); // load locally defined packages void scanLocalPackages(LocalPackageType type) { NativePath list_path = m_repositories[type].packagePath; Package[] packs; NativePath[] paths; if (!m_disableDefaultSearchPaths) try { auto local_package_file = list_path ~ LocalPackagesFilename; logDiagnostic("Looking for local package map at %s", local_package_file.toNativeString()); if( !existsFile(local_package_file) ) return; logDiagnostic("Try to load local package map at %s", local_package_file.toNativeString()); auto packlist = jsonFromFile(list_path ~ LocalPackagesFilename); enforce(packlist.type == Json.Type.array, LocalPackagesFilename~" must contain an array."); foreach( pentry; packlist ){ try { auto name = pentry["name"].get!string; auto path = NativePath(pentry["path"].get!string); if (name == "*") { paths ~= path; } else { auto ver = Version(pentry["version"].get!string); Package pp; if (!refresh_existing_packages) { foreach (p; m_repositories[type].localPackages) if (p.path == path) { pp = p; break; } } if (!pp) { auto infoFile = Package.findPackageFile(path); if (!infoFile.empty) pp = Package.load(path, infoFile); else { logWarn("Locally registered package %s %s was not found. Please run 'dub remove-local \"%s\"'.", name, ver, path.toNativeString()); auto info = Json.emptyObject; info["name"] = name; pp = new Package(info, path); } } if (pp.name != name) logWarn("Local package at %s has different name than %s (%s)", path.toNativeString(), name, pp.name); pp.version_ = ver; addPackages(packs, pp); } } catch( Exception e ){ logWarn("Error adding local package: %s", e.msg); } } } catch( Exception e ){ logDiagnostic("Loading of local package list at %s failed: %s", list_path.toNativeString(), e.msg); } m_repositories[type].localPackages = packs; m_repositories[type].searchPath = paths; } scanLocalPackages(LocalPackageType.system); scanLocalPackages(LocalPackageType.user); scanLocalPackages(LocalPackageType.package_); auto old_packages = m_packages; // rescan the system and user package folder void scanPackageFolder(NativePath path) { if( path.existsDirectory() ){ logDebug("iterating dir %s", path.toNativeString()); try foreach( pdir; iterateDirectory(path) ){ logDebug("iterating dir %s entry %s", path.toNativeString(), pdir.name); if (!pdir.isDirectory) continue; auto pack_path = path ~ (pdir.name ~ "/"); auto packageFile = Package.findPackageFile(pack_path); if (isManagedPath(path) && packageFile.empty) { // Search for a single directory within this directory which happen to be a prefix of pdir // This is to support new folder structure installed over the ancient one. foreach (subdir; iterateDirectory(path ~ (pdir.name ~ "/"))) if (subdir.isDirectory && pdir.name.startsWith(subdir.name)) {// eg: package vibe-d will be in "vibe-d-x.y.z/vibe-d" pack_path ~= subdir.name ~ "/"; packageFile = Package.findPackageFile(pack_path); break; } } if (packageFile.empty) continue; Package p; try { if (!refresh_existing_packages) foreach (pp; old_packages) if (pp.path == pack_path) { p = pp; break; } if (!p) p = Package.load(pack_path, packageFile); addPackages(m_packages, p); } catch( Exception e ){ logError("Failed to load package in %s: %s", pack_path, e.msg); logDiagnostic("Full error: %s", e.toString().sanitize()); } } catch(Exception e) logDiagnostic("Failed to enumerate %s packages: %s", path.toNativeString(), e.toString()); } } m_packages = null; foreach (p; this.completeSearchPath) scanPackageFolder(p); void loadOverrides(LocalPackageType type) { m_repositories[type].overrides = null; auto ovrfilepath = m_repositories[type].packagePath ~ LocalOverridesFilename; if (existsFile(ovrfilepath)) { foreach (entry; jsonFromFile(ovrfilepath)) { PackageOverride ovr; ovr.package_ = entry["name"].get!string; ovr.version_ = Dependency(entry["version"].get!string); if (auto pv = "targetVersion" in entry) ovr.targetVersion = Version(pv.get!string); if (auto pv = "targetPath" in entry) ovr.targetPath = NativePath(pv.get!string); m_repositories[type].overrides ~= ovr; } } } loadOverrides(LocalPackageType.package_); loadOverrides(LocalPackageType.user); loadOverrides(LocalPackageType.system); } alias Hash = ubyte[]; /// Generates a hash value for a given package. /// Some files or folders are ignored during the generation (like .dub and /// .svn folders) Hash hashPackage(Package pack) { string[] ignored_directories = [".git", ".dub", ".svn"]; // something from .dub_ignore or what? string[] ignored_files = []; SHA1 sha1; foreach(file; dirEntries(pack.path.toNativeString(), SpanMode.depth)) { if(file.isDir && ignored_directories.canFind(NativePath(file.name).head.name)) continue; else if(ignored_files.canFind(NativePath(file.name).head.name)) continue; sha1.put(cast(ubyte[])NativePath(file.name).head.name); if(file.isDir) { logDebug("Hashed directory name %s", NativePath(file.name).head); } else { sha1.put(openFile(NativePath(file.name)).readAll()); logDebug("Hashed file contents from %s", NativePath(file.name).head); } } auto hash = sha1.finish(); logDebug("Project hash: %s", hash); return hash[].dup; } private void writeLocalPackageList(LocalPackageType type) { Json[] newlist; foreach (p; m_repositories[type].searchPath) { auto entry = Json.emptyObject; entry["name"] = "*"; entry["path"] = p.toNativeString(); newlist ~= entry; } foreach (p; m_repositories[type].localPackages) { if (p.parentPackage) continue; // do not store sub packages auto entry = Json.emptyObject; entry["name"] = p.name; entry["version"] = p.version_.toString(); entry["path"] = p.path.toNativeString(); newlist ~= entry; } NativePath path = m_repositories[type].packagePath; if( !existsDirectory(path) ) mkdirRecurse(path.toNativeString()); writeJsonFile(path ~ LocalPackagesFilename, Json(newlist)); } private void writeLocalPackageOverridesFile(LocalPackageType type) { Json[] newlist; foreach (ovr; m_repositories[type].overrides) { auto jovr = Json.emptyObject; jovr["name"] = ovr.package_; jovr["version"] = ovr.version_.versionSpec; if (!ovr.targetPath.empty) jovr["targetPath"] = ovr.targetPath.toNativeString(); else jovr["targetVersion"] = ovr.targetVersion.toString(); newlist ~= jovr; } auto path = m_repositories[type].packagePath; if (!existsDirectory(path)) mkdirRecurse(path.toNativeString()); writeJsonFile(path ~ LocalOverridesFilename, Json(newlist)); } /// Adds the package and scans for subpackages. private void addPackages(ref Package[] dst_repos, Package pack) const { // Add the main package. dst_repos ~= pack; // Additionally to the internally defined subpackages, whose metadata // is loaded with the main dub.json, load all externally defined // packages after the package is available with all the data. foreach (spr; pack.subPackages) { Package sp; if (spr.path.length) { auto p = NativePath(spr.path); p.normalize(); enforce(!p.absolute, "Sub package paths must be sub paths of the parent package."); auto path = pack.path ~ p; if (!existsFile(path)) { logError("Package %s declared a sub-package, definition file is missing: %s", pack.name, path.toNativeString()); continue; } sp = Package.load(path, NativePath.init, pack); } else sp = new Package(spr.recipe, pack.path, pack); // Add the subpackage. try { dst_repos ~= sp; } catch (Exception e) { logError("Package '%s': Failed to load sub-package %s: %s", pack.name, spr.path.length ? spr.path : spr.recipe.name, e.msg); logDiagnostic("Full error: %s", e.toString().sanitize()); } } } } struct PackageOverride { string package_; Dependency version_; Version targetVersion; NativePath targetPath; this(string package_, Dependency version_, Version target_version) { this.package_ = package_; this.version_ = version_; this.targetVersion = target_version; } this(string package_, Dependency version_, NativePath target_path) { this.package_ = package_; this.version_ = version_; this.targetPath = target_path; } } enum LocalPackageType { package_, user, system } private enum LocalPackagesFilename = "local-packages.json"; private enum LocalOverridesFilename = "local-overrides.json"; private struct Repository { NativePath packagePath; NativePath[] searchPath; Package[] localPackages; PackageOverride[] overrides; this(NativePath path) { this.packagePath = path; } } dub-1.19.0/source/dub/packagesupplier.d000066400000000000000000000007151360435400500177550ustar00rootroot00000000000000/** +deprecated("Please use dub.packagesuppliers") Contains (remote) package supplier interface and implementations. +public import dub.packagesuppliers; Copyright: © 2012-2013 Matthias Dondorff, 2012-2016 Sönke Ludwig License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Matthias Dondorff */ deprecated("Please use dub.packagesuppliers") module dub.packagesupplier; public import dub.packagesuppliers; dub-1.19.0/source/dub/packagesuppliers/000077500000000000000000000000001360435400500177705ustar00rootroot00000000000000dub-1.19.0/source/dub/packagesuppliers/fallback.d000066400000000000000000000044351360435400500217020ustar00rootroot00000000000000module dub.packagesuppliers.fallback; import dub.packagesuppliers.packagesupplier; import std.typecons : AutoImplement; package abstract class AbstractFallbackPackageSupplier : PackageSupplier { protected import core.time : minutes; protected import std.datetime : Clock, SysTime; static struct Pair { PackageSupplier ps; SysTime failTime; } protected Pair[] m_suppliers; this(PackageSupplier[] suppliers) { assert(suppliers.length); m_suppliers.length = suppliers.length; foreach (i, ps; suppliers) m_suppliers[i].ps = ps; } override @property string description() { import std.algorithm.iteration : map; import std.format : format; return format("%s (fallbacks %-(%s, %))", m_suppliers[0].ps.description, m_suppliers[1 .. $].map!(pair => pair.ps.description)); } // Workaround https://issues.dlang.org/show_bug.cgi?id=2525 abstract override Version[] getVersions(string package_id); abstract override void fetchPackage(NativePath path, string package_id, Dependency dep, bool pre_release); abstract override Json fetchPackageRecipe(string package_id, Dependency dep, bool pre_release); abstract override SearchResult[] searchPackages(string query); } /** Combines two package suppliers and uses the second as fallback to handle failures. Assumes that both registries serve the same packages (--mirror). */ package(dub) alias FallbackPackageSupplier = AutoImplement!(AbstractFallbackPackageSupplier, fallback); private template fallback(T, alias func) { import std.format : format; enum fallback = q{ import dub.internal.vibecompat.core.log : logDiagnostic; Exception firstEx; try return m_suppliers[0].ps.%1$s(args); catch (Exception e) { logDiagnostic("Package supplier %%s failed with '%%s', trying fallbacks.", m_suppliers[0].ps.description, e.msg); firstEx = e; } immutable now = Clock.currTime; foreach (ref pair; m_suppliers[1 .. $]) { if (pair.failTime > now - 10.minutes) continue; try { scope (success) logDiagnostic("Fallback %%s succeeded", pair.ps.description); return pair.ps.%1$s(args); } catch (Exception e) { pair.failTime = now; logDiagnostic("Fallback package supplier %%s failed with '%%s'.", pair.ps.description, e.msg); } } throw firstEx; }.format(__traits(identifier, func)); } dub-1.19.0/source/dub/packagesuppliers/filesystem.d000066400000000000000000000055301360435400500223240ustar00rootroot00000000000000module dub.packagesuppliers.filesystem; import dub.packagesuppliers.packagesupplier; /** File system based package supplier. This package supplier searches a certain directory for files with names of the form "[package name]-[version].zip". */ class FileSystemPackageSupplier : PackageSupplier { import dub.internal.vibecompat.core.log; version (Have_vibe_core) import dub.internal.vibecompat.inet.path : toNativeString; import std.exception : enforce; private { NativePath m_path; } this(NativePath root) { m_path = root; } override @property string description() { return "file repository at "~m_path.toNativeString(); } Version[] getVersions(string package_id) { import std.algorithm.sorting : sort; import std.file : dirEntries, DirEntry, SpanMode; import std.conv : to; Version[] ret; foreach (DirEntry d; dirEntries(m_path.toNativeString(), package_id~"*", SpanMode.shallow)) { NativePath p = NativePath(d.name); logDebug("Entry: %s", p); enforce(to!string(p.head)[$-4..$] == ".zip"); auto vers = p.head.name[package_id.length+1..$-4]; logDebug("Version: %s", vers); ret ~= Version(vers); } ret.sort(); return ret; } void fetchPackage(NativePath path, string packageId, Dependency dep, bool pre_release) { import dub.internal.vibecompat.core.file : copyFile, existsFile; enforce(path.absolute); logInfo("Storing package '"~packageId~"', version requirements: %s", dep); auto filename = bestPackageFile(packageId, dep, pre_release); enforce(existsFile(filename)); copyFile(filename, path); } Json fetchPackageRecipe(string packageId, Dependency dep, bool pre_release) { import std.array : split; import std.path : stripExtension; import dub.internal.utils : packageInfoFileFromZip; import dub.recipe.io : parsePackageRecipe; import dub.recipe.json : toJson; auto filePath = bestPackageFile(packageId, dep, pre_release); string packageFileName; string packageFileContent = packageInfoFileFromZip(filePath, packageFileName); auto recipe = parsePackageRecipe(packageFileContent, packageFileName); Json json = toJson(recipe); json["version"] = filePath.toNativeString().split("-")[$-1].stripExtension(); return json; } SearchResult[] searchPackages(string query) { // TODO! return null; } private NativePath bestPackageFile(string packageId, Dependency dep, bool pre_release) { import std.algorithm.iteration : filter; import std.array : array; import std.format : format; NativePath toPath(Version ver) { return m_path ~ (packageId ~ "-" ~ ver.toString() ~ ".zip"); } auto versions = getVersions(packageId).filter!(v => dep.matches(v)).array; enforce(versions.length > 0, format("No package %s found matching %s", packageId, dep)); foreach_reverse (ver; versions) { if (pre_release || !ver.isPreRelease) return toPath(ver); } return toPath(versions[$-1]); } } dub-1.19.0/source/dub/packagesuppliers/maven.d000066400000000000000000000071701360435400500212500ustar00rootroot00000000000000module dub.packagesuppliers.maven; import dub.packagesuppliers.packagesupplier; /** Maven repository based package supplier. This package supplier connects to a maven repository to search for available packages. */ class MavenRegistryPackageSupplier : PackageSupplier { import dub.internal.utils : retryDownload, HTTPStatusException; import dub.internal.vibecompat.data.json : serializeToJson; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.url : URL; import std.datetime : Clock, Duration, hours, SysTime, UTC; private { enum httpTimeout = 16; URL m_mavenUrl; struct CacheEntry { Json data; SysTime cacheTime; } CacheEntry[string] m_metadataCache; Duration m_maxCacheTime; } this(URL mavenUrl) { m_mavenUrl = mavenUrl; m_maxCacheTime = 24.hours(); } override @property string description() { return "maven repository at "~m_mavenUrl.toString(); } Version[] getVersions(string package_id) { import std.algorithm.sorting : sort; auto md = getMetadata(package_id); if (md.type == Json.Type.null_) return null; Version[] ret; foreach (json; md["versions"]) { auto cur = Version(json["version"].get!string); ret ~= cur; } ret.sort(); return ret; } void fetchPackage(NativePath path, string packageId, Dependency dep, bool pre_release) { import std.format : format; auto md = getMetadata(packageId); Json best = getBestPackage(md, packageId, dep, pre_release); if (best.type == Json.Type.null_) return; auto vers = best["version"].get!string; auto url = m_mavenUrl~NativePath("%s/%s/%s-%s.zip".format(packageId, vers, packageId, vers)); try { retryDownload(url, path, 3, httpTimeout); return; } catch(HTTPStatusException e) { if (e.status == 404) throw e; else logDebug("Failed to download package %s from %s", packageId, url); } catch(Exception e) { logDebug("Failed to download package %s from %s", packageId, url); } throw new Exception("Failed to download package %s from %s".format(packageId, url)); } Json fetchPackageRecipe(string packageId, Dependency dep, bool pre_release) { auto md = getMetadata(packageId); return getBestPackage(md, packageId, dep, pre_release); } private Json getMetadata(string packageId) { import std.xml; auto now = Clock.currTime(UTC()); if (auto pentry = packageId in m_metadataCache) { if (pentry.cacheTime + m_maxCacheTime > now) return pentry.data; m_metadataCache.remove(packageId); } auto url = m_mavenUrl~NativePath(packageId~"/maven-metadata.xml"); logDebug("Downloading maven metadata for %s", packageId); string xmlData; try xmlData = cast(string)retryDownload(url, 3, httpTimeout); catch(HTTPStatusException e) { if (e.status == 404) { logDebug("Maven metadata %s not found at %s (404): %s", packageId, description, e.msg); return Json(null); } else throw e; } auto json = Json(["name": Json(packageId), "versions": Json.emptyArray]); auto xml = new DocumentParser(xmlData); xml.onStartTag["versions"] = (ElementParser xml) { xml.onEndTag["version"] = (in Element e) { json["versions"] ~= serializeToJson(["name": packageId, "version": e.text]); }; xml.parse(); }; xml.parse(); m_metadataCache[packageId] = CacheEntry(json, now); return json; } SearchResult[] searchPackages(string query) { // Only exact search is supported // This enables retrival of dub packages on dub run auto md = getMetadata(query); if (md.type == Json.Type.null_) return []; auto json = getBestPackage(md, query, Dependency(">=0.0.0"), true); return [SearchResult(json["name"].opt!string, "", json["version"].opt!string)]; } } dub-1.19.0/source/dub/packagesuppliers/package.d000066400000000000000000000005171360435400500215330ustar00rootroot00000000000000module dub.packagesuppliers; /** Contains (remote) package supplier interface and implementations. */ public import dub.packagesuppliers.fallback; public import dub.packagesuppliers.filesystem; public import dub.packagesuppliers.packagesupplier; public import dub.packagesuppliers.maven; public import dub.packagesuppliers.registry; dub-1.19.0/source/dub/packagesuppliers/packagesupplier.d000066400000000000000000000056221360435400500233210ustar00rootroot00000000000000module dub.packagesuppliers.packagesupplier; public import dub.dependency : Dependency, Version; public import dub.internal.vibecompat.core.file : NativePath; public import dub.internal.vibecompat.data.json : Json; /** Base interface for remote package suppliers. Provides functionality necessary to query package versions, recipes and contents. */ interface PackageSupplier { /// Represents a single package search result. static struct SearchResult { string name, description, version_; } /// Returns a human-readable representation of the package supplier. @property string description(); /** Retrieves a list of all available versions(/branches) of a package. Throws: Throws an exception if the package name is not known, or if an error occurred while retrieving the version list. */ Version[] getVersions(string package_id); /** Downloads a package and stores it as a ZIP file. Params: path = Absolute path of the target ZIP file package_id = Name of the package to retrieve dep: Version constraint to match against pre_release: If true, matches the latest pre-release version. Otherwise prefers stable versions. */ void fetchPackage(NativePath path, string package_id, Dependency dep, bool pre_release); /** Retrieves only the recipe of a particular package. Params: package_id = Name of the package of which to retrieve the recipe dep: Version constraint to match against pre_release: If true, matches the latest pre-release version. Otherwise prefers stable versions. */ Json fetchPackageRecipe(string package_id, Dependency dep, bool pre_release); /** Searches for packages matching the given search query term. Search queries are currently a simple list of words separated by white space. Results will get ordered from best match to worst. */ SearchResult[] searchPackages(string query); } // TODO: Could drop the "best package" behavior and let retrievePackage/ // getPackageDescription take a Version instead of Dependency. But note // this means that two requests to the registry are necessary to retrieve // a package recipe instead of one (first get version list, then the // package recipe) package Json getBestPackage(Json metadata, string packageId, Dependency dep, bool pre_release) { import std.exception : enforce; if (metadata.type == Json.Type.null_) return metadata; Json best = null; Version bestver; foreach (json; metadata["versions"]) { auto cur = Version(json["version"].get!string); if (!dep.matches(cur)) continue; if (best == null) best = json; else if (pre_release) { if (cur > bestver) best = json; } else if (bestver.isPreRelease) { if (!cur.isPreRelease || cur > bestver) best = json; } else if (!cur.isPreRelease && cur > bestver) best = json; bestver = Version(cast(string)best["version"]); } enforce(best != null, "No package candidate found for "~packageId~" "~dep.toString()); return best; } dub-1.19.0/source/dub/packagesuppliers/registry.d000066400000000000000000000067111360435400500220120ustar00rootroot00000000000000module dub.packagesuppliers.registry; import dub.packagesuppliers.packagesupplier; package enum PackagesPath = "packages"; /** Online registry based package supplier. This package supplier connects to an online registry (e.g. $(LINK https://code.dlang.org/)) to search for available packages. */ class RegistryPackageSupplier : PackageSupplier { import dub.internal.utils : download, retryDownload, HTTPStatusException; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json : parseJson, parseJsonString, serializeToJson; import dub.internal.vibecompat.inet.url : URL; import std.datetime : Clock, Duration, hours, SysTime, UTC; private { URL m_registryUrl; struct CacheEntry { Json data; SysTime cacheTime; } CacheEntry[string] m_metadataCache; Duration m_maxCacheTime; } this(URL registry) { m_registryUrl = registry; m_maxCacheTime = 24.hours(); } override @property string description() { return "registry at "~m_registryUrl.toString(); } Version[] getVersions(string package_id) { import std.algorithm.sorting : sort; auto md = getMetadata(package_id); if (md.type == Json.Type.null_) return null; Version[] ret; foreach (json; md["versions"]) { auto cur = Version(cast(string)json["version"]); ret ~= cur; } ret.sort(); return ret; } void fetchPackage(NativePath path, string packageId, Dependency dep, bool pre_release) { import std.array : replace; import std.format : format; auto md = getMetadata(packageId); Json best = getBestPackage(md, packageId, dep, pre_release); if (best.type == Json.Type.null_) return; auto vers = best["version"].get!string; auto url = m_registryUrl ~ NativePath(PackagesPath~"/"~packageId~"/"~vers~".zip"); try { retryDownload(url, path); return; } catch(HTTPStatusException e) { if (e.status == 404) throw e; else logDebug("Failed to download package %s from %s", packageId, url); } catch(Exception e) { logDebug("Failed to download package %s from %s", packageId, url); } throw new Exception("Failed to download package %s from %s".format(packageId, url)); } Json fetchPackageRecipe(string packageId, Dependency dep, bool pre_release) { auto md = getMetadata(packageId); return getBestPackage(md, packageId, dep, pre_release); } private Json getMetadata(string packageId) { auto now = Clock.currTime(UTC()); if (auto pentry = packageId in m_metadataCache) { if (pentry.cacheTime + m_maxCacheTime > now) return pentry.data; m_metadataCache.remove(packageId); } auto url = m_registryUrl ~ NativePath("api/packages/infos?packages=[\"" ~ packageId ~ "\"]&include_dependencies=true&minimize=true"); logDebug("Downloading metadata for %s", packageId); string jsonData; jsonData = cast(string)retryDownload(url); Json json = parseJsonString(jsonData, url.toString()); foreach (pkg, info; json.get!(Json[string])) { logDebug("adding %s to metadata cache", pkg); m_metadataCache[pkg] = CacheEntry(info, now); } return json[packageId]; } SearchResult[] searchPackages(string query) { import std.array : array; import std.algorithm.iteration : map; import std.uri : encodeComponent; auto url = m_registryUrl; url.localURI = "/api/packages/search?q="~encodeComponent(query); string data; data = cast(string)retryDownload(url); return data.parseJson.opt!(Json[]) .map!(j => SearchResult(j["name"].opt!string, j["description"].opt!string, j["version"].opt!string)) .array; } } dub-1.19.0/source/dub/platform.d000066400000000000000000000176411360435400500164300ustar00rootroot00000000000000/** Build platform identification and specification matching. This module is useful for determining the build platform for a certain machine and compiler invocation. Example applications include classifying CI slave machines. It also contains means to match build platforms against a platform specification string as used in package reciptes. Copyright: © 2012-2017 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.platform; import std.array; // archCheck, compilerCheck, and platformCheck are used below and in // generatePlatformProbeFile, so they've been extracted into these strings // that can be reused. // Try to not use phobos in the probes to avoid long import times. /// private enum string platformCheck = q{ string[] ret; version(Windows) ret ~= "windows"; version(linux) ret ~= "linux"; version(Posix) ret ~= "posix"; version(OSX) ret ~= "osx"; version(FreeBSD) ret ~= "freebsd"; version(OpenBSD) ret ~= "openbsd"; version(NetBSD) ret ~= "netbsd"; version(DragonFlyBSD) ret ~= "dragonflybsd"; version(BSD) ret ~= "bsd"; version(Solaris) ret ~= "solaris"; version(AIX) ret ~= "aix"; version(Haiku) ret ~= "haiku"; version(SkyOS) ret ~= "skyos"; version(SysV3) ret ~= "sysv3"; version(SysV4) ret ~= "sysv4"; version(Hurd) ret ~= "hurd"; version(Android) ret ~= "android"; version(Cygwin) ret ~= "cygwin"; version(MinGW) ret ~= "mingw"; version(WebAssembly) ret ~= "wasm"; return ret; }; /// private enum string archCheck = q{ string[] ret; version(X86) ret ~= "x86"; version(X86_64) ret ~= "x86_64"; version(ARM) ret ~= "arm"; version(AArch64) ret ~= "aarch64"; version(ARM_Thumb) ret ~= "arm_thumb"; version(ARM_SoftFloat) ret ~= "arm_softfloat"; version(ARM_HardFloat) ret ~= "arm_hardfloat"; version(PPC) ret ~= "ppc"; version(PPC_SoftFP) ret ~= "ppc_softfp"; version(PPC_HardFP) ret ~= "ppc_hardfp"; version(PPC64) ret ~= "ppc64"; version(IA64) ret ~= "ia64"; version(MIPS) ret ~= "mips"; version(MIPS32) ret ~= "mips32"; version(MIPS64) ret ~= "mips64"; version(MIPS_O32) ret ~= "mips_o32"; version(MIPS_N32) ret ~= "mips_n32"; version(MIPS_O64) ret ~= "mips_o64"; version(MIPS_N64) ret ~= "mips_n64"; version(MIPS_EABI) ret ~= "mips_eabi"; version(MIPS_NoFloat) ret ~= "mips_nofloat"; version(MIPS_SoftFloat) ret ~= "mips_softfloat"; version(MIPS_HardFloat) ret ~= "mips_hardfloat"; version(SPARC) ret ~= "sparc"; version(SPARC_V8Plus) ret ~= "sparc_v8plus"; version(SPARC_SoftFP) ret ~= "sparc_softfp"; version(SPARC_HardFP) ret ~= "sparc_hardfp"; version(SPARC64) ret ~= "sparc64"; version(S390) ret ~= "s390"; version(S390X) ret ~= "s390x"; version(HPPA) ret ~= "hppa"; version(HPPA64) ret ~= "hppa64"; version(SH) ret ~= "sh"; version(SH64) ret ~= "sh64"; version(Alpha) ret ~= "alpha"; version(Alpha_SoftFP) ret ~= "alpha_softfp"; version(Alpha_HardFP) ret ~= "alpha_hardfp"; return ret; }; /// private enum string compilerCheck = q{ version(DigitalMars) return "dmd"; else version(GNU) return "gdc"; else version(LDC) return "ldc"; else version(SDC) return "sdc"; else return null; }; /** Determines the full build platform used for the current build. Note that the `BuildPlatform.compilerBinary` field will be left empty. See_Also: `determinePlatform`, `determineArchitecture`, `determineCompiler` */ BuildPlatform determineBuildPlatform() { BuildPlatform ret; ret.platform = determinePlatform(); ret.architecture = determineArchitecture(); ret.compiler = determineCompiler(); ret.frontendVersion = __VERSION__; return ret; } /** Returns a list of platform identifiers that apply to the current build. Example results are `["windows"]` or `["posix", "osx"]`. The identifiers correspond to the compiler defined version constants built into the language, except that they are converted to lower case. See_Also: `determineBuildPlatform` */ string[] determinePlatform() { mixin(platformCheck); } /** Returns a list of architecture identifiers that apply to the current build. Example results are `["x86_64"]` or `["arm", "arm_softfloat"]`. The identifiers correspond to the compiler defined version constants built into the language, except that they are converted to lower case. See_Also: `determineBuildPlatform` */ string[] determineArchitecture() { mixin(archCheck); } /** Determines the canonical compiler name used for the current build. The possible values currently are "dmd", "gdc", "ldc" or "sdc". If an unknown compiler is used, this function will return an empty string. See_Also: `determineBuildPlatform` */ string determineCompiler() { mixin(compilerCheck); } /** Matches a platform specification string against a build platform. Specifications are build upon the following scheme, where each component is optional (indicated by []), but the order is obligatory: "[-platform][-architecture][-compiler]" So the following strings are valid specifications: `"-windows-x86-dmd"`, `"-dmd"`, `"-arm"`, `"-arm-dmd"`, `"-windows-dmd"` Params: platform = The build platform to match agains the platform specification specification = The specification being matched. It must either be an empty string or start with a dash. Returns: `true` if the given specification matches the build platform, `false` otherwise. Using an empty string as the platform specification will always result in a match. */ bool matchesSpecification(in BuildPlatform platform, const(char)[] specification) { import std.string : format; import std.algorithm : canFind, splitter; import std.exception : enforce; if (specification.empty) return true; if (platform == BuildPlatform.any) return true; auto splitted = specification.splitter('-'); assert(!splitted.empty, "No valid platform specification! The leading hyphen is required!"); splitted.popFront(); // Drop leading empty match. enforce(!splitted.empty, format("Platform specification, if present, must not be empty: \"%s\"", specification)); if (platform.platform.canFind(splitted.front)) { splitted.popFront(); if (splitted.empty) return true; } if (platform.architecture.canFind(splitted.front)) { splitted.popFront(); if (splitted.empty) return true; } if (platform.compiler == splitted.front) { splitted.popFront(); enforce(splitted.empty, "No valid specification! The compiler has to be the last element: " ~ specification); return true; } return false; } /// unittest { auto platform=BuildPlatform(["posix", "linux"], ["x86_64"], "dmd"); assert(platform.matchesSpecification("")); assert(platform.matchesSpecification("-posix")); assert(platform.matchesSpecification("-linux")); assert(platform.matchesSpecification("-linux-dmd")); assert(platform.matchesSpecification("-linux-x86_64-dmd")); assert(platform.matchesSpecification("-x86_64")); assert(!platform.matchesSpecification("-windows")); assert(!platform.matchesSpecification("-ldc")); assert(!platform.matchesSpecification("-windows-dmd")); } /// Represents a platform a package can be build upon. struct BuildPlatform { /// Special constant used to denote matching any build platform. enum any = BuildPlatform(null, null, null, null, -1); /// Platform identifiers, e.g. ["posix", "windows"] string[] platform; /// CPU architecture identifiers, e.g. ["x86", "x86_64"] string[] architecture; /// Canonical compiler name e.g. "dmd" string compiler; /// Compiler binary name e.g. "ldmd2" string compilerBinary; /// Compiled frontend version (e.g. `2067` for frontend versions 2.067.x) int frontendVersion; /// Compiler version e.g. "1.11.0" string compilerVersion; /// Frontend version string from frontendVersion /// e.g: 2067 => "2.067" string frontendVersionString() const { import std.format : format; const maj = frontendVersion / 1000; const min = frontendVersion % 1000; return format("%d.%03d", maj, min); } /// unittest { BuildPlatform bp; bp.frontendVersion = 2067; assert(bp.frontendVersionString == "2.067"); } } dub-1.19.0/source/dub/project.d000066400000000000000000001627471360435400500162620ustar00rootroot00000000000000/** Representing a full project, with a root Package and several dependencies. Copyright: © 2012-2013 Matthias Dondorff, 2012-2016 Sönke Ludwig License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Matthias Dondorff, Sönke Ludwig */ module dub.project; import dub.compilers.compiler; import dub.dependency; import dub.description; import dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.url; import dub.package_; import dub.packagemanager; import dub.generators.generator; import std.algorithm; import std.array; import std.conv : to; import std.datetime; import std.exception : enforce; import std.string; import std.encoding : sanitize; /** Represents a full project, a root package with its dependencies and package selection. All dependencies must be available locally so that the package dependency graph can be built. Use `Project.reinit` if necessary for reloading dependencies after more packages are available. */ class Project { private { PackageManager m_packageManager; Json m_packageSettings; Package m_rootPackage; Package[] m_dependencies; Package[][Package] m_dependees; SelectedVersions m_selections; string[] m_missingDependencies; string[string] m_overriddenConfigs; } /** Loads a project. Params: package_manager = Package manager instance to use for loading dependencies project_path = Path of the root package to load pack = An existing `Package` instance to use as the root package */ this(PackageManager package_manager, NativePath project_path) { Package pack; auto packageFile = Package.findPackageFile(project_path); if (packageFile.empty) { logWarn("There was no package description found for the application in '%s'.", project_path.toNativeString()); pack = new Package(PackageRecipe.init, project_path); } else { pack = package_manager.getOrLoadPackage(project_path, packageFile); } this(package_manager, pack); } /// ditto this(PackageManager package_manager, Package pack) { m_packageManager = package_manager; m_rootPackage = pack; m_packageSettings = Json.emptyObject; try m_packageSettings = jsonFromFile(m_rootPackage.path ~ ".dub/dub.json", true); catch(Exception t) logDiagnostic("Failed to read .dub/dub.json: %s", t.msg); auto selverfile = m_rootPackage.path ~ SelectedVersions.defaultFile; if (existsFile(selverfile)) { try m_selections = new SelectedVersions(selverfile); catch(Exception e) { logWarn("Failed to load %s: %s", SelectedVersions.defaultFile, e.msg); logDiagnostic("Full error: %s", e.toString().sanitize); m_selections = new SelectedVersions; } } else m_selections = new SelectedVersions; reinit(); } /** List of all resolved dependencies. This includes all direct and indirect dependencies of all configurations combined. Optional dependencies that were not chosen are not included. */ @property const(Package[]) dependencies() const { return m_dependencies; } /// The root package of the project. @property inout(Package) rootPackage() inout { return m_rootPackage; } /// The versions to use for all dependencies. Call reinit() after changing these. @property inout(SelectedVersions) selections() inout { return m_selections; } /// Package manager instance used by the project. @property inout(PackageManager) packageManager() inout { return m_packageManager; } /** Determines if all dependencies necessary to build have been collected. If this function returns `false`, it may be necessary to add more entries to `selections`, or to use `Dub.upgrade` to automatically select all missing dependencies. */ bool hasAllDependencies() const { return m_missingDependencies.length == 0; } /// Sorted list of missing dependencies. string[] missingDependencies() { return m_missingDependencies; } /** Allows iteration of the dependency tree in topological order */ int delegate(int delegate(ref Package)) getTopologicalPackageList(bool children_first = false, Package root_package = null, string[string] configs = null) { // ugly way to avoid code duplication since inout isn't compatible with foreach type inference return cast(int delegate(int delegate(ref Package)))(cast(const)this).getTopologicalPackageList(children_first, root_package, configs); } /// ditto int delegate(int delegate(ref const Package)) getTopologicalPackageList(bool children_first = false, in Package root_package = null, string[string] configs = null) const { const(Package) rootpack = root_package ? root_package : m_rootPackage; int iterator(int delegate(ref const Package) del) { int ret = 0; bool[const(Package)] visited; void perform_rec(in Package p){ if( p in visited ) return; visited[p] = true; if( !children_first ){ ret = del(p); if( ret ) return; } auto cfg = configs.get(p.name, null); PackageDependency[] deps; if (!cfg.length) deps = p.getAllDependencies(); else { auto depmap = p.getDependencies(cfg); deps = depmap.byKey.map!(k => PackageDependency(k, depmap[k])).array; } deps.sort!((a, b) => a.name < b.name); foreach (d; deps) { auto dependency = getDependency(d.name, true); assert(dependency || d.spec.optional, format("Non-optional dependency %s of %s not found in dependency tree!?.", d.name, p.name)); if(dependency) perform_rec(dependency); if( ret ) return; } if( children_first ){ ret = del(p); if( ret ) return; } } perform_rec(rootpack); return ret; } return &iterator; } /** Retrieves a particular dependency by name. Params: name = (Qualified) package name of the dependency is_optional = If set to true, will return `null` for unsatisfiable dependencies instead of throwing an exception. */ inout(Package) getDependency(string name, bool is_optional) inout { foreach(dp; m_dependencies) if( dp.name == name ) return dp; if (!is_optional) throw new Exception("Unknown dependency: "~name); else return null; } /** Returns the name of the default build configuration for the specified target platform. Params: platform = The target build platform allow_non_library_configs = If set to true, will use the first possible configuration instead of the first "executable" configuration. */ string getDefaultConfiguration(BuildPlatform platform, bool allow_non_library_configs = true) const { auto cfgs = getPackageConfigs(platform, null, allow_non_library_configs); return cfgs[m_rootPackage.name]; } /** Overrides the configuration chosen for a particular package in the dependency graph. Setting a certain configuration here is equivalent to removing all but one configuration from the package. Params: package_ = The package for which to force selecting a certain dependency config = Name of the configuration to force */ void overrideConfiguration(string package_, string config) { auto p = getDependency(package_, true); enforce(p !is null, format("Package '%s', marked for configuration override, is not present in dependency graph.", package_)); enforce(p.configurations.canFind(config), format("Package '%s' does not have a configuration named '%s'.", package_, config)); m_overriddenConfigs[package_] = config; } /** Performs basic validation of various aspects of the package. This will emit warnings to `stderr` if any discouraged names or dependency patterns are found. */ void validate() { // some basic package lint m_rootPackage.warnOnSpecialCompilerFlags(); string nameSuggestion() { string ret; ret ~= `Please modify the "name" field in %s accordingly.`.format(m_rootPackage.recipePath.toNativeString()); if (!m_rootPackage.recipe.buildSettings.targetName.length) { if (m_rootPackage.recipePath.head.name.endsWith(".sdl")) { ret ~= ` You can then add 'targetName "%s"' to keep the current executable name.`.format(m_rootPackage.name); } else { ret ~= ` You can then add '"targetName": "%s"' to keep the current executable name.`.format(m_rootPackage.name); } } return ret; } if (m_rootPackage.name != m_rootPackage.name.toLower()) { logWarn(`WARNING: DUB package names should always be lower case. %s`, nameSuggestion()); } else if (!m_rootPackage.recipe.name.all!(ch => ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9' || ch == '-' || ch == '_')) { logWarn(`WARNING: DUB package names may only contain alphanumeric characters, ` ~ `as well as '-' and '_'. %s`, nameSuggestion()); } enforce(!m_rootPackage.name.canFind(' '), "Aborting due to the package name containing spaces."); foreach (d; m_rootPackage.getAllDependencies()) if (d.spec.isExactVersion && d.spec.version_.isBranch) { logWarn("WARNING: A deprecated branch based version specification is used " ~ "for the dependency %s. Please use numbered versions instead. Also " ~ "note that you can still use the %s file to override a certain " ~ "dependency to use a branch instead.", d.name, SelectedVersions.defaultFile); } // search for orphan sub configurations void warnSubConfig(string pack, string config) { logWarn("The sub configuration directive \"%s\" -> \"%s\" " ~ "references a package that is not specified as a dependency " ~ "and will have no effect.", pack, config); } void checkSubConfig(string pack, string config) { auto p = getDependency(pack, true); if (p && !p.configurations.canFind(config)) { logWarn("The sub configuration directive \"%s\" -> \"%s\" " ~ "references a configuration that does not exist.", pack, config); } } auto globalbs = m_rootPackage.getBuildSettings(); foreach (p, c; globalbs.subConfigurations) { if (p !in globalbs.dependencies) warnSubConfig(p, c); else checkSubConfig(p, c); } foreach (c; m_rootPackage.configurations) { auto bs = m_rootPackage.getBuildSettings(c); foreach (p, c; bs.subConfigurations) { if (p !in bs.dependencies && p !in globalbs.dependencies) warnSubConfig(p, c); else checkSubConfig(p, c); } } // check for version specification mismatches bool[Package] visited; void validateDependenciesRec(Package pack) { // perform basic package linting pack.simpleLint(); foreach (d; pack.getAllDependencies()) { auto basename = getBasePackageName(d.name); if (m_selections.hasSelectedVersion(basename)) { auto selver = m_selections.getSelectedVersion(basename); if (d.spec.merge(selver) == Dependency.invalid) { logWarn("Selected package %s %s does not match the dependency specification %s in package %s. Need to \"dub upgrade\"?", basename, selver, d.spec, pack.name); } } auto deppack = getDependency(d.name, true); if (deppack in visited) continue; visited[deppack] = true; if (deppack) validateDependenciesRec(deppack); } } validateDependenciesRec(m_rootPackage); } /// Reloads dependencies. void reinit() { m_dependencies = null; m_missingDependencies = []; m_packageManager.refresh(false); void collectDependenciesRec(Package pack, int depth = 0) { auto indent = replicate(" ", depth); logDebug("%sCollecting dependencies for %s", indent, pack.name); indent ~= " "; foreach (dep; pack.getAllDependencies()) { Dependency vspec = dep.spec; Package p; auto basename = getBasePackageName(dep.name); auto subname = getSubPackageName(dep.name); // non-optional and optional-default dependencies (if no selections file exists) // need to be satisfied bool is_desired = !vspec.optional || m_selections.hasSelectedVersion(basename) || (vspec.default_ && m_selections.bare); if (dep.name == m_rootPackage.basePackage.name) { vspec = Dependency(m_rootPackage.version_); p = m_rootPackage.basePackage; } else if (basename == m_rootPackage.basePackage.name) { vspec = Dependency(m_rootPackage.version_); try p = m_packageManager.getSubPackage(m_rootPackage.basePackage, subname, false); catch (Exception e) { logDiagnostic("%sError getting sub package %s: %s", indent, dep.name, e.msg); if (is_desired) m_missingDependencies ~= dep.name; continue; } } else if (m_selections.hasSelectedVersion(basename)) { vspec = m_selections.getSelectedVersion(basename); if (vspec.path.empty) p = m_packageManager.getBestPackage(dep.name, vspec); else { auto path = vspec.path; if (!path.absolute) path = m_rootPackage.path ~ path; p = m_packageManager.getOrLoadPackage(path, NativePath.init, true); if (subname.length) p = m_packageManager.getSubPackage(p, subname, true); } } else if (m_dependencies.canFind!(d => getBasePackageName(d.name) == basename)) { auto idx = m_dependencies.countUntil!(d => getBasePackageName(d.name) == basename); auto bp = m_dependencies[idx].basePackage; vspec = Dependency(bp.path); if (subname.length) p = m_packageManager.getSubPackage(bp, subname, false); else p = bp; } else { logDiagnostic("%sVersion selection for dependency %s (%s) of %s is missing.", indent, basename, dep.name, pack.name); } if (!p && !vspec.path.empty) { NativePath path = vspec.path; if (!path.absolute) path = pack.path ~ path; logDiagnostic("%sAdding local %s in %s", indent, dep.name, path); p = m_packageManager.getOrLoadPackage(path, NativePath.init, true); if (p.parentPackage !is null) { logWarn("%sSub package %s must be referenced using the path to it's parent package.", indent, dep.name); p = p.parentPackage; } if (subname.length) p = m_packageManager.getSubPackage(p, subname, false); enforce(p.name == dep.name, format("Path based dependency %s is referenced with a wrong name: %s vs. %s", path.toNativeString(), dep.name, p.name)); } if (!p) { logDiagnostic("%sMissing dependency %s %s of %s", indent, dep.name, vspec, pack.name); if (is_desired) m_missingDependencies ~= dep.name; continue; } if (!m_dependencies.canFind(p)) { logDiagnostic("%sFound dependency %s %s", indent, dep.name, vspec.toString()); m_dependencies ~= p; if (basename == m_rootPackage.basePackage.name) p.warnOnSpecialCompilerFlags(); collectDependenciesRec(p, depth+1); } m_dependees[p] ~= pack; //enforce(p !is null, "Failed to resolve dependency "~dep.name~" "~vspec.toString()); } } collectDependenciesRec(m_rootPackage); m_missingDependencies.sort(); } /// Returns the name of the root package. @property string name() const { return m_rootPackage ? m_rootPackage.name : "app"; } /// Returns the names of all configurations of the root package. @property string[] configurations() const { return m_rootPackage.configurations; } /// Returns a map with the configuration for all packages in the dependency tree. string[string] getPackageConfigs(in BuildPlatform platform, string config, bool allow_non_library = true) const { struct Vertex { string pack, config; } struct Edge { size_t from, to; } Vertex[] configs; Edge[] edges; string[][string] parents; parents[m_rootPackage.name] = null; foreach (p; getTopologicalPackageList()) foreach (d; p.getAllDependencies()) parents[d.name] ~= p.name; size_t createConfig(string pack, string config) { foreach (i, v; configs) if (v.pack == pack && v.config == config) return i; assert(pack !in m_overriddenConfigs || config == m_overriddenConfigs[pack]); logDebug("Add config %s %s", pack, config); configs ~= Vertex(pack, config); return configs.length-1; } bool haveConfig(string pack, string config) { return configs.any!(c => c.pack == pack && c.config == config); } size_t createEdge(size_t from, size_t to) { auto idx = edges.countUntil(Edge(from, to)); if (idx >= 0) return idx; logDebug("Including %s %s -> %s %s", configs[from].pack, configs[from].config, configs[to].pack, configs[to].config); edges ~= Edge(from, to); return edges.length-1; } void removeConfig(size_t i) { logDebug("Eliminating config %s for %s", configs[i].config, configs[i].pack); auto had_dep_to_pack = new bool[configs.length]; auto still_has_dep_to_pack = new bool[configs.length]; edges = edges.filter!((e) { if (e.to == i) { had_dep_to_pack[e.from] = true; return false; } else if (configs[e.to].pack == configs[i].pack) { still_has_dep_to_pack[e.from] = true; } if (e.from == i) return false; return true; }).array; configs[i] = Vertex.init; // mark config as removed // also remove any configs that cannot be satisfied anymore foreach (j; 0 .. configs.length) if (j != i && had_dep_to_pack[j] && !still_has_dep_to_pack[j]) removeConfig(j); } bool isReachable(string pack, string conf) { if (pack == configs[0].pack && configs[0].config == conf) return true; foreach (e; edges) if (configs[e.to].pack == pack && configs[e.to].config == conf) return true; return false; //return (pack == configs[0].pack && conf == configs[0].config) || edges.canFind!(e => configs[e.to].pack == pack && configs[e.to].config == config); } bool isReachableByAllParentPacks(size_t cidx) { bool[string] r; foreach (p; parents[configs[cidx].pack]) r[p] = false; foreach (e; edges) { if (e.to != cidx) continue; if (auto pp = configs[e.from].pack in r) *pp = true; } foreach (bool v; r) if (!v) return false; return true; } string[] allconfigs_path; void determineDependencyConfigs(in Package p, string c) { string[][string] depconfigs; foreach (d; p.getAllDependencies()) { auto dp = getDependency(d.name, true); if (!dp) continue; string[] cfgs; if (auto pc = dp.name in m_overriddenConfigs) cfgs = [*pc]; else { auto subconf = p.getSubConfiguration(c, dp, platform); if (!subconf.empty) cfgs = [subconf]; else cfgs = dp.getPlatformConfigurations(platform); } cfgs = cfgs.filter!(c => haveConfig(d.name, c)).array; // if no valid configuration was found for a dependency, don't include the // current configuration if (!cfgs.length) { logDebug("Skip %s %s (missing configuration for %s)", p.name, c, dp.name); return; } depconfigs[d.name] = cfgs; } // add this configuration to the graph size_t cidx = createConfig(p.name, c); foreach (d; p.getAllDependencies()) foreach (sc; depconfigs.get(d.name, null)) createEdge(cidx, createConfig(d.name, sc)); } // create a graph of all possible package configurations (package, config) -> (subpackage, subconfig) void determineAllConfigs(in Package p) { auto idx = allconfigs_path.countUntil(p.name); enforce(idx < 0, format("Detected dependency cycle: %s", (allconfigs_path[idx .. $] ~ p.name).join("->"))); allconfigs_path ~= p.name; scope (exit) allconfigs_path.length--; // first, add all dependency configurations foreach (d; p.getAllDependencies) { auto dp = getDependency(d.name, true); if (!dp) continue; determineAllConfigs(dp); } // for each configuration, determine the configurations usable for the dependencies if (auto pc = p.name in m_overriddenConfigs) determineDependencyConfigs(p, *pc); else foreach (c; p.getPlatformConfigurations(platform, p is m_rootPackage && allow_non_library)) determineDependencyConfigs(p, c); } if (config.length) createConfig(m_rootPackage.name, config); determineAllConfigs(m_rootPackage); // successively remove configurations until only one configuration per package is left bool changed; do { // remove all configs that are not reachable by all parent packages changed = false; foreach (i, ref c; configs) { if (c == Vertex.init) continue; // ignore deleted configurations if (!isReachableByAllParentPacks(i)) { logDebug("%s %s NOT REACHABLE by all of (%s):", c.pack, c.config, parents[c.pack]); removeConfig(i); changed = true; } } // when all edges are cleaned up, pick one package and remove all but one config if (!changed) { foreach (p; getTopologicalPackageList()) { size_t cnt = 0; foreach (i, ref c; configs) if (c.pack == p.name && ++cnt > 1) { logDebug("NON-PRIMARY: %s %s", c.pack, c.config); removeConfig(i); } if (cnt > 1) { changed = true; break; } } } } while (changed); // print out the resulting tree foreach (e; edges) logDebug(" %s %s -> %s %s", configs[e.from].pack, configs[e.from].config, configs[e.to].pack, configs[e.to].config); // return the resulting configuration set as an AA string[string] ret; foreach (c; configs) { if (c == Vertex.init) continue; // ignore deleted configurations assert(ret.get(c.pack, c.config) == c.config, format("Conflicting configurations for %s found: %s vs. %s", c.pack, c.config, ret[c.pack])); logDebug("Using configuration '%s' for %s", c.config, c.pack); ret[c.pack] = c.config; } // check for conflicts (packages missing in the final configuration graph) void checkPacksRec(in Package pack) { auto pc = pack.name in ret; enforce(pc !is null, "Could not resolve configuration for package "~pack.name); foreach (p, dep; pack.getDependencies(*pc)) { auto deppack = getDependency(p, dep.optional); if (deppack) checkPacksRec(deppack); } } checkPacksRec(m_rootPackage); return ret; } /** * Fills `dst` with values from this project. * * `dst` gets initialized according to the given platform and config. * * Params: * dst = The BuildSettings struct to fill with data. * gsettings = The generator settings to retrieve the values for. * config = Values of the given configuration will be retrieved. * root_package = If non null, use it instead of the project's real root package. * shallow = If true, collects only build settings for the main package (including inherited settings) and doesn't stop on target type none and sourceLibrary. */ void addBuildSettings(ref BuildSettings dst, in GeneratorSettings gsettings, string config, in Package root_package = null, bool shallow = false) const { import dub.internal.utils : stripDlangSpecialChars; auto configs = getPackageConfigs(gsettings.platform, config); foreach (pkg; this.getTopologicalPackageList(false, root_package, configs)) { auto pkg_path = pkg.path.toNativeString(); dst.addVersions(["Have_" ~ stripDlangSpecialChars(pkg.name)]); assert(pkg.name in configs, "Missing configuration for "~pkg.name); logDebug("Gathering build settings for %s (%s)", pkg.name, configs[pkg.name]); auto psettings = pkg.getBuildSettings(gsettings.platform, configs[pkg.name]); if (psettings.targetType != TargetType.none) { if (shallow && pkg !is m_rootPackage) psettings.sourceFiles = null; processVars(dst, this, pkg, psettings, gsettings); if (psettings.importPaths.empty) logWarn(`Package %s (configuration "%s") defines no import paths, use {"importPaths": [...]} or the default package directory structure to fix this.`, pkg.name, configs[pkg.name]); if (psettings.mainSourceFile.empty && pkg is m_rootPackage && psettings.targetType == TargetType.executable) logWarn(`Executable configuration "%s" of package %s defines no main source file, this may cause certain build modes to fail. Add an explicit "mainSourceFile" to the package description to fix this.`, configs[pkg.name], pkg.name); } if (pkg is m_rootPackage) { if (!shallow) { enforce(psettings.targetType != TargetType.none, "Main package has target type \"none\" - stopping build."); enforce(psettings.targetType != TargetType.sourceLibrary, "Main package has target type \"sourceLibrary\" which generates no target - stopping build."); } dst.targetType = psettings.targetType; dst.targetPath = psettings.targetPath; dst.targetName = psettings.targetName; if (!psettings.workingDirectory.empty) dst.workingDirectory = processVars(psettings.workingDirectory, this, pkg, gsettings, true); if (psettings.mainSourceFile.length) dst.mainSourceFile = processVars(psettings.mainSourceFile, this, pkg, gsettings, true); } } // always add all version identifiers of all packages foreach (pkg; this.getTopologicalPackageList(false, null, configs)) { auto psettings = pkg.getBuildSettings(gsettings.platform, configs[pkg.name]); dst.addVersions(psettings.versions); } } /** Fills `dst` with build settings specific to the given build type. Params: dst = The `BuildSettings` instance to add the build settings to gsettings = Target generator settings build_type = Name of the build type for_root_package = Selects if the build settings are for the root package or for one of the dependencies. Unittest flags will only be added to the root package. */ void addBuildTypeSettings(ref BuildSettings dst, in GeneratorSettings gsettings, bool for_root_package = true) { bool usedefflags = !(dst.requirements & BuildRequirement.noDefaultFlags); if (usedefflags) { BuildSettings btsettings; m_rootPackage.addBuildTypeSettings(btsettings, gsettings.platform, gsettings.buildType); if (!for_root_package) { // don't propagate unittest switch to dependencies, as dependent // unit tests aren't run anyway and the additional code may // cause linking to fail on Windows (issue #640) btsettings.removeOptions(BuildOption.unittests); } processVars(dst, this, m_rootPackage, btsettings, gsettings); } } /// Outputs a build description of the project, including its dependencies. ProjectDescription describe(GeneratorSettings settings) { import dub.generators.targetdescription; // store basic build parameters ProjectDescription ret; ret.rootPackage = m_rootPackage.name; ret.configuration = settings.config; ret.buildType = settings.buildType; ret.compiler = settings.platform.compiler; ret.architecture = settings.platform.architecture; ret.platform = settings.platform.platform; // collect high level information about projects (useful for IDE display) auto configs = getPackageConfigs(settings.platform, settings.config); ret.packages ~= m_rootPackage.describe(settings.platform, settings.config); foreach (dep; m_dependencies) ret.packages ~= dep.describe(settings.platform, configs[dep.name]); foreach (p; getTopologicalPackageList(false, null, configs)) ret.packages[ret.packages.countUntil!(pp => pp.name == p.name)].active = true; if (settings.buildType.length) { // collect build target information (useful for build tools) auto gen = new TargetDescriptionGenerator(this); try { gen.generate(settings); ret.targets = gen.targetDescriptions; ret.targetLookup = gen.targetDescriptionLookup; } catch (Exception e) { logDiagnostic("Skipping targets description: %s", e.msg); logDebug("Full error: %s", e.toString().sanitize); } } return ret; } private string[] listBuildSetting(string attributeName)(BuildPlatform platform, string config, ProjectDescription projectDescription, Compiler compiler, bool disableEscaping) { return listBuildSetting!attributeName(platform, getPackageConfigs(platform, config), projectDescription, compiler, disableEscaping); } private string[] listBuildSetting(string attributeName)(BuildPlatform platform, string[string] configs, ProjectDescription projectDescription, Compiler compiler, bool disableEscaping) { if (compiler) return formatBuildSettingCompiler!attributeName(platform, configs, projectDescription, compiler, disableEscaping); else return formatBuildSettingPlain!attributeName(platform, configs, projectDescription); } // Output a build setting formatted for a compiler private string[] formatBuildSettingCompiler(string attributeName)(BuildPlatform platform, string[string] configs, ProjectDescription projectDescription, Compiler compiler, bool disableEscaping) { import std.process : escapeShellFileName; import std.path : dirSeparator; assert(compiler); auto targetDescription = projectDescription.lookupTarget(projectDescription.rootPackage); auto buildSettings = targetDescription.buildSettings; string[] values; switch (attributeName) { case "dflags": case "linkerFiles": case "mainSourceFile": case "importFiles": values = formatBuildSettingPlain!attributeName(platform, configs, projectDescription); break; case "lflags": case "sourceFiles": case "versions": case "debugVersions": case "importPaths": case "stringImportPaths": case "options": auto bs = buildSettings.dup; bs.dflags = null; // Ensure trailing slash on directory paths auto ensureTrailingSlash = (string path) => path.endsWith(dirSeparator) ? path : path ~ dirSeparator; static if (attributeName == "importPaths") bs.importPaths = bs.importPaths.map!(ensureTrailingSlash).array(); else static if (attributeName == "stringImportPaths") bs.stringImportPaths = bs.stringImportPaths.map!(ensureTrailingSlash).array(); compiler.prepareBuildSettings(bs, platform, BuildSetting.all & ~to!BuildSetting(attributeName)); values = bs.dflags; break; case "libs": auto bs = buildSettings.dup; bs.dflags = null; bs.lflags = null; bs.sourceFiles = null; bs.targetType = TargetType.none; // Force Compiler to NOT omit dependency libs when package is a library. compiler.prepareBuildSettings(bs, platform, BuildSetting.all & ~to!BuildSetting(attributeName)); if (bs.lflags) values = compiler.lflagsToDFlags( bs.lflags ); else if (bs.sourceFiles) values = compiler.lflagsToDFlags( bs.sourceFiles ); else values = bs.dflags; break; default: assert(0); } // Escape filenames and paths if(!disableEscaping) { switch (attributeName) { case "mainSourceFile": case "linkerFiles": case "copyFiles": case "importFiles": case "stringImportFiles": case "sourceFiles": case "importPaths": case "stringImportPaths": return values.map!(escapeShellFileName).array(); default: return values; } } return values; } // Output a build setting without formatting for any particular compiler private string[] formatBuildSettingPlain(string attributeName)(BuildPlatform platform, string[string] configs, ProjectDescription projectDescription) { import std.path : buildNormalizedPath, dirSeparator; import std.range : only; string[] list; enforce(attributeName == "targetType" || projectDescription.lookupRootPackage().targetType != TargetType.none, "Target type is 'none'. Cannot list build settings."); static if (attributeName == "targetType") if (projectDescription.rootPackage !in projectDescription.targetLookup) return ["none"]; auto targetDescription = projectDescription.lookupTarget(projectDescription.rootPackage); auto buildSettings = targetDescription.buildSettings; // Return any BuildSetting member attributeName as a range of strings. Don't attempt to fixup values. // allowEmptyString: When the value is a string (as opposed to string[]), // is empty string an actual permitted value instead of // a missing value? auto getRawBuildSetting(Package pack, bool allowEmptyString) { auto value = __traits(getMember, buildSettings, attributeName); static if( is(typeof(value) == string[]) ) return value; else static if( is(typeof(value) == string) ) { auto ret = only(value); // only() has a different return type from only(value), so we // have to empty the range rather than just returning only(). if(value.empty && !allowEmptyString) { ret.popFront(); assert(ret.empty); } return ret; } else static if( is(typeof(value) == enum) ) return only(value); else static if( is(typeof(value) == BuildRequirements) ) return only(cast(BuildRequirement) cast(int) value.values); else static if( is(typeof(value) == BuildOptions) ) return only(cast(BuildOption) cast(int) value.values); else static assert(false, "Type of BuildSettings."~attributeName~" is unsupported."); } // Adjust BuildSetting member attributeName as needed. // Returns a range of strings. auto getFixedBuildSetting(Package pack) { // Is relative path(s) to a directory? enum isRelativeDirectory = attributeName == "importPaths" || attributeName == "stringImportPaths" || attributeName == "targetPath" || attributeName == "workingDirectory"; // Is relative path(s) to a file? enum isRelativeFile = attributeName == "sourceFiles" || attributeName == "linkerFiles" || attributeName == "importFiles" || attributeName == "stringImportFiles" || attributeName == "copyFiles" || attributeName == "mainSourceFile"; // For these, empty string means "main project directory", not "missing value" enum allowEmptyString = attributeName == "targetPath" || attributeName == "workingDirectory"; enum isEnumBitfield = attributeName == "requirements" || attributeName == "options"; enum isEnum = attributeName == "targetType"; auto values = getRawBuildSetting(pack, allowEmptyString); string fixRelativePath(string importPath) { return buildNormalizedPath(pack.path.toString(), importPath); } static string ensureTrailingSlash(string path) { return path.endsWith(dirSeparator) ? path : path ~ dirSeparator; } static if(isRelativeDirectory) { // Return full paths for the paths, making sure a // directory separator is on the end of each path. return values.map!(fixRelativePath).map!(ensureTrailingSlash); } else static if(isRelativeFile) { // Return full paths. return values.map!(fixRelativePath); } else static if(isEnumBitfield) return bitFieldNames(values.front); else static if (isEnum) return [values.front.to!string]; else return values; } foreach(value; getFixedBuildSetting(m_rootPackage)) { list ~= value; } return list; } // The "compiler" arg is for choosing which compiler the output should be formatted for, // or null to imply "list" format. private string[] listBuildSetting(BuildPlatform platform, string[string] configs, ProjectDescription projectDescription, string requestedData, Compiler compiler, bool disableEscaping) { // Certain data cannot be formatter for a compiler if (compiler) { switch (requestedData) { case "target-type": case "target-path": case "target-name": case "working-directory": case "string-import-files": case "copy-files": case "extra-dependency-files": case "pre-generate-commands": case "post-generate-commands": case "pre-build-commands": case "post-build-commands": enforce(false, "--data="~requestedData~" can only be used with --data-list or --data-0."); break; case "requirements": enforce(false, "--data=requirements can only be used with --data-list or --data-0. Use --data=options instead."); break; default: break; } } import std.typetuple : TypeTuple; auto args = TypeTuple!(platform, configs, projectDescription, compiler, disableEscaping); switch (requestedData) { case "target-type": return listBuildSetting!"targetType"(args); case "target-path": return listBuildSetting!"targetPath"(args); case "target-name": return listBuildSetting!"targetName"(args); case "working-directory": return listBuildSetting!"workingDirectory"(args); case "main-source-file": return listBuildSetting!"mainSourceFile"(args); case "dflags": return listBuildSetting!"dflags"(args); case "lflags": return listBuildSetting!"lflags"(args); case "libs": return listBuildSetting!"libs"(args); case "linker-files": return listBuildSetting!"linkerFiles"(args); case "source-files": return listBuildSetting!"sourceFiles"(args); case "copy-files": return listBuildSetting!"copyFiles"(args); case "extra-dependency-files": return listBuildSetting!"extraDependencyFiles"(args); case "versions": return listBuildSetting!"versions"(args); case "debug-versions": return listBuildSetting!"debugVersions"(args); case "import-paths": return listBuildSetting!"importPaths"(args); case "string-import-paths": return listBuildSetting!"stringImportPaths"(args); case "import-files": return listBuildSetting!"importFiles"(args); case "string-import-files": return listBuildSetting!"stringImportFiles"(args); case "pre-generate-commands": return listBuildSetting!"preGenerateCommands"(args); case "post-generate-commands": return listBuildSetting!"postGenerateCommands"(args); case "pre-build-commands": return listBuildSetting!"preBuildCommands"(args); case "post-build-commands": return listBuildSetting!"postBuildCommands"(args); case "pre-run-commands": return listBuildSetting!"preRunCommands"(args); case "post-run-commands": return listBuildSetting!"postRunCommands"(args); case "requirements": return listBuildSetting!"requirements"(args); case "options": return listBuildSetting!"options"(args); default: enforce(false, "--data="~requestedData~ " is not a valid option. See 'dub describe --help' for accepted --data= values."); } assert(0); } /// Outputs requested data for the project, optionally including its dependencies. string[] listBuildSettings(GeneratorSettings settings, string[] requestedData, ListBuildSettingsFormat list_type) { import dub.compilers.utils : isLinkerFile; auto projectDescription = describe(settings); auto configs = getPackageConfigs(settings.platform, settings.config); PackageDescription packageDescription; foreach (pack; projectDescription.packages) { if (pack.name == projectDescription.rootPackage) packageDescription = pack; } if (projectDescription.rootPackage in projectDescription.targetLookup) { // Copy linker files from sourceFiles to linkerFiles auto target = projectDescription.lookupTarget(projectDescription.rootPackage); foreach (file; target.buildSettings.sourceFiles.filter!(f => isLinkerFile(settings.platform, f))) target.buildSettings.addLinkerFiles(file); // Remove linker files from sourceFiles target.buildSettings.sourceFiles = target.buildSettings.sourceFiles .filter!(a => !isLinkerFile(settings.platform, a)) .array(); projectDescription.lookupTarget(projectDescription.rootPackage) = target; } Compiler compiler; bool no_escape; final switch (list_type) with (ListBuildSettingsFormat) { case list: break; case listNul: no_escape = true; break; case commandLine: compiler = settings.compiler; break; case commandLineNul: compiler = settings.compiler; no_escape = true; break; } auto result = requestedData .map!(dataName => listBuildSetting(settings.platform, configs, projectDescription, dataName, compiler, no_escape)); final switch (list_type) with (ListBuildSettingsFormat) { case list: return result.map!(l => l.join("\n")).array(); case listNul: return result.map!(l => l.join("\0")).array; case commandLine: return result.map!(l => l.join(" ")).array; case commandLineNul: return result.map!(l => l.join("\0")).array; } } /** Saves the currently selected dependency versions to disk. The selections will be written to a file named `SelectedVersions.defaultFile` ("dub.selections.json") within the directory of the root package. Any existing file will get overwritten. */ void saveSelections() { assert(m_selections !is null, "Cannot save selections for non-disk based project (has no selections)."); if (m_selections.hasSelectedVersion(m_rootPackage.basePackage.name)) m_selections.deselectVersion(m_rootPackage.basePackage.name); auto path = m_rootPackage.path ~ SelectedVersions.defaultFile; if (m_selections.dirty || !existsFile(path)) m_selections.save(path); } deprecated bool isUpgradeCacheUpToDate() { return false; } deprecated Dependency[string] getUpgradeCache() { return null; } /** Sets a new set of versions for the upgrade cache. */ void setUpgradeCache(Dependency[string] versions) { logDebug("markUpToDate"); Json create(ref Json json, string object) { if (json[object].type == Json.Type.undefined) json[object] = Json.emptyObject; return json[object]; } create(m_packageSettings, "dub"); m_packageSettings["dub"]["lastUpgrade"] = Clock.currTime().toISOExtString(); create(m_packageSettings["dub"], "cachedUpgrades"); foreach (p, d; versions) m_packageSettings["dub"]["cachedUpgrades"][p] = SelectedVersions.dependencyToJson(d); writeDubJson(); } private void writeDubJson() { import std.file : exists, mkdir; // don't bother to write an empty file if( m_packageSettings.length == 0 ) return; try { logDebug("writeDubJson"); auto dubpath = m_rootPackage.path~".dub"; if( !exists(dubpath.toNativeString()) ) mkdir(dubpath.toNativeString()); auto dstFile = openFile((dubpath~"dub.json").toString(), FileMode.createTrunc); scope(exit) dstFile.close(); dstFile.writePrettyJsonString(m_packageSettings); } catch( Exception e ){ logWarn("Could not write .dub/dub.json."); } } } /// Determines the output format used for `Project.listBuildSettings`. enum ListBuildSettingsFormat { list, /// Newline separated list entries listNul, /// NUL character separated list entries (unescaped) commandLine, /// Formatted for compiler command line (one data list per line) commandLineNul, /// NUL character separated list entries (unescaped, data lists separated by two NUL characters) } /// Indicates where a package has been or should be placed to. enum PlacementLocation { /// Packages retrieved with 'local' will be placed in the current folder /// using the package name as destination. local, /// Packages with 'userWide' will be placed in a folder accessible by /// all of the applications from the current user. user, /// Packages retrieved with 'systemWide' will be placed in a shared folder, /// which can be accessed by all users of the system. system } void processVars(ref BuildSettings dst, in Project project, in Package pack, BuildSettings settings, in GeneratorSettings gsettings, bool include_target_settings = false) { dst.addDFlags(processVars(project, pack, gsettings, settings.dflags)); dst.addLFlags(processVars(project, pack, gsettings, settings.lflags)); dst.addLibs(processVars(project, pack, gsettings, settings.libs)); dst.addSourceFiles(processVars!true(project, pack, gsettings, settings.sourceFiles, true)); dst.addImportFiles(processVars(project, pack, gsettings, settings.importFiles, true)); dst.addStringImportFiles(processVars(project, pack, gsettings, settings.stringImportFiles, true)); dst.addCopyFiles(processVars(project, pack, gsettings, settings.copyFiles, true)); dst.addExtraDependencyFiles(processVars(project, pack, gsettings, settings.extraDependencyFiles, true)); dst.addVersions(processVars(project, pack, gsettings, settings.versions)); dst.addDebugVersions(processVars(project, pack, gsettings, settings.debugVersions)); dst.addVersionFilters(processVars(project, pack, gsettings, settings.versionFilters)); dst.addDebugVersionFilters(processVars(project, pack, gsettings, settings.debugVersionFilters)); dst.addImportPaths(processVars(project, pack, gsettings, settings.importPaths, true)); dst.addStringImportPaths(processVars(project, pack, gsettings, settings.stringImportPaths, true)); dst.addPreGenerateCommands(processVars(project, pack, gsettings, settings.preGenerateCommands)); dst.addPostGenerateCommands(processVars(project, pack, gsettings, settings.postGenerateCommands)); dst.addPreBuildCommands(processVars(project, pack, gsettings, settings.preBuildCommands)); dst.addPostBuildCommands(processVars(project, pack, gsettings, settings.postBuildCommands)); dst.addPreRunCommands(processVars(project, pack, gsettings, settings.preRunCommands)); dst.addPostRunCommands(processVars(project, pack, gsettings, settings.postRunCommands)); dst.addRequirements(settings.requirements); dst.addOptions(settings.options); if (include_target_settings) { dst.targetType = settings.targetType; dst.targetPath = processVars(settings.targetPath, project, pack, gsettings, true); dst.targetName = settings.targetName; if (!settings.workingDirectory.empty) dst.workingDirectory = processVars(settings.workingDirectory, project, pack, gsettings, true); if (settings.mainSourceFile.length) dst.mainSourceFile = processVars(settings.mainSourceFile, project, pack, gsettings, true); } } private string[] processVars(bool glob = false)(in Project project, in Package pack, in GeneratorSettings gsettings, string[] vars, bool are_paths = false) { auto ret = appender!(string[])(); processVars!glob(ret, project, pack, gsettings, vars, are_paths); return ret.data; } private void processVars(bool glob = false)(ref Appender!(string[]) dst, in Project project, in Package pack, in GeneratorSettings gsettings, string[] vars, bool are_paths = false) { static if (glob) alias process = processVarsWithGlob!(Project, Package); else alias process = processVars!(Project, Package); foreach (var; vars) dst.put(process(var, project, pack, gsettings, are_paths)); } private string processVars(Project, Package)(string var, in Project project, in Package pack, in GeneratorSettings gsettings, bool is_path) { var = var.expandVars!(varName => getVariable(varName, project, pack, gsettings)); if (!is_path) return var; auto p = NativePath(var); if (!p.absolute) return (pack.path ~ p).toNativeString(); else return p.toNativeString(); } private string[] processVarsWithGlob(Project, Package)(string var, in Project project, in Package pack, in GeneratorSettings gsettings, bool is_path) { assert(is_path, "can't glob something that isn't a path"); string res = processVars(var, project, pack, gsettings, is_path); // Find the unglobbed prefix and iterate from there. size_t i = 0; size_t sepIdx = 0; loop: while (i < res.length) { switch_: switch (res[i]) { case '*', '?', '[', '{': break loop; case '/': sepIdx = i; goto default; default: ++i; break switch_; } } if (i == res.length) //no globbing found in the path return [res]; import std.path : globMatch; import std.file : dirEntries, SpanMode; return dirEntries(res[0 .. sepIdx], SpanMode.depth) .map!(de => de.name) .filter!(name => globMatch(name, res)) .array; } /// Expand variables using `$VAR_NAME` or `${VAR_NAME}` syntax. /// `$$` escapes itself and is expanded to a single `$`. private string expandVars(alias expandVar)(string s) { import std.functional : not; auto result = appender!string; static bool isVarChar(char c) { import std.ascii; return isAlphaNum(c) || c == '_'; } while (true) { auto pos = s.indexOf('$'); if (pos < 0) { result.put(s); return result.data; } result.put(s[0 .. pos]); s = s[pos + 1 .. $]; enforce(s.length > 0, "Variable name expected at end of string"); switch (s[0]) { case '$': result.put("$"); s = s[1 .. $]; break; case '{': pos = s.indexOf('}'); enforce(pos >= 0, "Could not find '}' to match '${'"); result.put(expandVar(s[1 .. pos])); s = s[pos + 1 .. $]; break; default: pos = s.representation.countUntil!(not!isVarChar); if (pos < 0) pos = s.length; result.put(expandVar(s[0 .. pos])); s = s[pos .. $]; break; } } } unittest { string[string] vars = [ "A" : "a", "B" : "b", ]; string expandVar(string name) { auto p = name in vars; enforce(p, name); return *p; } assert(expandVars!expandVar("") == ""); assert(expandVars!expandVar("x") == "x"); assert(expandVars!expandVar("$$") == "$"); assert(expandVars!expandVar("x$$") == "x$"); assert(expandVars!expandVar("$$x") == "$x"); assert(expandVars!expandVar("$$$$") == "$$"); assert(expandVars!expandVar("x$A") == "xa"); assert(expandVars!expandVar("x$$A") == "x$A"); assert(expandVars!expandVar("$A$B") == "ab"); assert(expandVars!expandVar("${A}$B") == "ab"); assert(expandVars!expandVar("$A${B}") == "ab"); assert(expandVars!expandVar("a${B}") == "ab"); assert(expandVars!expandVar("${A}b") == "ab"); import std.exception : assertThrown; assertThrown(expandVars!expandVar("$")); assertThrown(expandVars!expandVar("${}")); assertThrown(expandVars!expandVar("$|")); assertThrown(expandVars!expandVar("x$")); assertThrown(expandVars!expandVar("$X")); assertThrown(expandVars!expandVar("${")); assertThrown(expandVars!expandVar("${X")); // https://github.com/dlang/dmd/pull/9275 assert(expandVars!expandVar("$${DUB_EXE:-dub}") == "${DUB_EXE:-dub}"); } // Keep the following list up-to-date if adding more build settings variables. /// List of variables that can be used in build settings package(dub) immutable buildSettingsVars = [ "ARCH", "PLATFORM", "PLATFORM_POSIX", "BUILD_TYPE" ]; private string getVariable(Project, Package)(string name, in Project project, in Package pack, in GeneratorSettings gsettings) { import dub.internal.utils : getDUBExePath; import std.process : environment, escapeShellFileName; import std.uni : asUpperCase; NativePath path; if (name == "PACKAGE_DIR") path = pack.path; else if (name == "ROOT_PACKAGE_DIR") path = project.rootPackage.path; if (name.endsWith("_PACKAGE_DIR")) { auto pname = name[0 .. $-12]; foreach (prj; project.getTopologicalPackageList()) if (prj.name.asUpperCase.map!(a => a == '-' ? '_' : a).equal(pname)) { path = prj.path; break; } } if (!path.empty) { // no trailing slash for clean path concatenation (see #1392) path.endsWithSlash = false; return path.toNativeString(); } if (name == "DUB") { return getDUBExePath(gsettings.platform.compilerBinary); } if (name == "ARCH") { foreach (a; gsettings.platform.architecture) return a; return ""; } if (name == "PLATFORM") { import std.algorithm : filter; foreach (p; gsettings.platform.platform.filter!(p => p != "posix")) return p; foreach (p; gsettings.platform.platform) return p; return ""; } if (name == "PLATFORM_POSIX") { import std.algorithm : canFind; if (gsettings.platform.platform.canFind("posix")) return "posix"; foreach (p; gsettings.platform.platform) return p; return ""; } if (name == "BUILD_TYPE") return gsettings.buildType; auto envvar = environment.get(name); if (envvar !is null) return envvar; throw new Exception("Invalid variable: "~name); } unittest { static struct MockPackage { this(string name) { this.name = name; version (Posix) path = NativePath("/pkgs/"~name); else version (Windows) path = NativePath(`C:\pkgs\`~name); // see 4d4017c14c, #268, and #1392 for why this all package paths end on slash internally path.endsWithSlash = true; } string name; NativePath path; } static struct MockProject { MockPackage rootPackage; inout(MockPackage)[] getTopologicalPackageList() inout { return _dependencies; } private: MockPackage[] _dependencies; } MockProject proj = { rootPackage: MockPackage("root"), _dependencies: [MockPackage("dep1"), MockPackage("dep2")] }; auto pack = MockPackage("test"); GeneratorSettings gsettings; enum isPath = true; import std.path : dirSeparator; static NativePath woSlash(NativePath p) { p.endsWithSlash = false; return p; } // basic vars assert(processVars("Hello $PACKAGE_DIR", proj, pack, gsettings, !isPath) == "Hello "~woSlash(pack.path).toNativeString); assert(processVars("Hello $ROOT_PACKAGE_DIR", proj, pack, gsettings, !isPath) == "Hello "~woSlash(proj.rootPackage.path).toNativeString.chomp(dirSeparator)); assert(processVars("Hello $DEP1_PACKAGE_DIR", proj, pack, gsettings, !isPath) == "Hello "~woSlash(proj._dependencies[0].path).toNativeString); // ${VAR} replacements assert(processVars("Hello ${PACKAGE_DIR}"~dirSeparator~"foobar", proj, pack, gsettings, !isPath) == "Hello "~(pack.path ~ "foobar").toNativeString); assert(processVars("Hello $PACKAGE_DIR"~dirSeparator~"foobar", proj, pack, gsettings, !isPath) == "Hello "~(pack.path ~ "foobar").toNativeString); // test with isPath assert(processVars("local", proj, pack, gsettings, isPath) == (pack.path ~ "local").toNativeString); assert(processVars("foo/$$ESCAPED", proj, pack, gsettings, isPath) == (pack.path ~ "foo/$ESCAPED").toNativeString); assert(processVars("$$ESCAPED", proj, pack, gsettings, !isPath) == "$ESCAPED"); // test other env variables import std.process : environment; environment["MY_ENV_VAR"] = "blablabla"; assert(processVars("$MY_ENV_VAR", proj, pack, gsettings, !isPath) == "blablabla"); assert(processVars("${MY_ENV_VAR}suffix", proj, pack, gsettings, !isPath) == "blablablasuffix"); assert(processVars("$MY_ENV_VAR-suffix", proj, pack, gsettings, !isPath) == "blablabla-suffix"); assert(processVars("$MY_ENV_VAR:suffix", proj, pack, gsettings, !isPath) == "blablabla:suffix"); assert(processVars("$MY_ENV_VAR$MY_ENV_VAR", proj, pack, gsettings, !isPath) == "blablablablablabla"); environment.remove("MY_ENV_VAR"); } /** Holds and stores a set of version selections for package dependencies. This is the runtime representation of the information contained in "dub.selections.json" within a package's directory. */ final class SelectedVersions { private struct Selected { Dependency dep; //Dependency[string] packages; } private { enum FileVersion = 1; Selected[string] m_selections; bool m_dirty = false; // has changes since last save bool m_bare = true; } /// Default file name to use for storing selections. enum defaultFile = "dub.selections.json"; /// Constructs a new empty version selection. this() {} /** Constructs a new version selection from JSON data. The structure of the JSON document must match the contents of the "dub.selections.json" file. */ this(Json data) { deserialize(data); m_dirty = false; } /** Constructs a new version selections from an existing JSON file. */ this(NativePath path) { auto json = jsonFromFile(path); deserialize(json); m_dirty = false; m_bare = false; } /// Returns a list of names for all packages that have a version selection. @property string[] selectedPackages() const { return m_selections.keys; } /// Determines if any changes have been made after loading the selections from a file. @property bool dirty() const { return m_dirty; } /// Determine if this set of selections is still empty (but not `clear`ed). @property bool bare() const { return m_bare && !m_dirty; } /// Removes all selections. void clear() { m_selections = null; m_dirty = true; } /// Duplicates the set of selected versions from another instance. void set(SelectedVersions versions) { m_selections = versions.m_selections.dup; m_dirty = true; } /// Selects a certain version for a specific package. void selectVersion(string package_id, Version version_) { if (auto ps = package_id in m_selections) { if (ps.dep == Dependency(version_)) return; } m_selections[package_id] = Selected(Dependency(version_)/*, issuer*/); m_dirty = true; } /// Selects a certain path for a specific package. void selectVersion(string package_id, NativePath path) { if (auto ps = package_id in m_selections) { if (ps.dep == Dependency(path)) return; } m_selections[package_id] = Selected(Dependency(path)); m_dirty = true; } /// Removes the selection for a particular package. void deselectVersion(string package_id) { m_selections.remove(package_id); m_dirty = true; } /// Determines if a particular package has a selection set. bool hasSelectedVersion(string packageId) const { return (packageId in m_selections) !is null; } /** Returns the selection for a particular package. Note that the returned `Dependency` can either have the `Dependency.path` property set to a non-empty value, in which case this is a path based selection, or its `Dependency.version_` property is valid and it is a version selection. */ Dependency getSelectedVersion(string packageId) const { enforce(hasSelectedVersion(packageId)); return m_selections[packageId].dep; } /** Stores the selections to disk. The target file will be written in JSON format. Usually, `defaultFile` should be used as the file name and the directory should be the root directory of the project's root package. */ void save(NativePath path) { Json json = serialize(); auto file = openFile(path, FileMode.createTrunc); scope(exit) file.close(); assert(json.type == Json.Type.object); assert(json.length == 2); assert(json["versions"].type != Json.Type.undefined); file.write("{\n\t\"fileVersion\": "); file.writeJsonString(json["fileVersion"]); file.write(",\n\t\"versions\": {"); auto vers = json["versions"].get!(Json[string]); bool first = true; foreach (k; vers.byKey.array.sort()) { if (!first) file.write(","); else first = false; file.write("\n\t\t"); file.writeJsonString(Json(k)); file.write(": "); file.writeJsonString(vers[k]); } file.write("\n\t}\n}\n"); m_dirty = false; m_bare = false; } static Json dependencyToJson(Dependency d) { if (d.path.empty) return Json(d.version_.toString()); else return serializeToJson(["path": d.path.toString()]); } static Dependency dependencyFromJson(Json j) { if (j.type == Json.Type.string) return Dependency(Version(j.get!string)); else if (j.type == Json.Type.object) return Dependency(NativePath(j["path"].get!string)); else throw new Exception(format("Unexpected type for dependency: %s", j.type)); } Json serialize() const { Json json = serializeToJson(m_selections); Json serialized = Json.emptyObject; serialized["fileVersion"] = FileVersion; serialized["versions"] = Json.emptyObject; foreach (p, v; m_selections) serialized["versions"][p] = dependencyToJson(v.dep); return serialized; } private void deserialize(Json json) { enforce(cast(int)json["fileVersion"] == FileVersion, "Mismatched dub.select.json version: " ~ to!string(cast(int)json["fileVersion"]) ~ "vs. " ~to!string(FileVersion)); clear(); scope(failure) clear(); foreach (string p, v; json["versions"]) m_selections[p] = Selected(dependencyFromJson(v)); } } dub-1.19.0/source/dub/recipe/000077500000000000000000000000001360435400500156755ustar00rootroot00000000000000dub-1.19.0/source/dub/recipe/io.d000066400000000000000000000127031360435400500164540ustar00rootroot00000000000000/** Package recipe reading/writing facilities. Copyright: © 2015-2016, Sönke Ludwig License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.recipe.io; import dub.recipe.packagerecipe; import dub.internal.vibecompat.inet.path; /** Reads a package recipe from a file. The file format (JSON/SDLang) will be determined from the file extension. Params: filename = NativePath of the package recipe file parent_name = Optional name of the parent package (if this is a sub package) Returns: Returns the package recipe contents Throws: Throws an exception if an I/O or syntax error occurs */ PackageRecipe readPackageRecipe(string filename, string parent_name = null) { return readPackageRecipe(NativePath(filename), parent_name); } /// ditto PackageRecipe readPackageRecipe(NativePath filename, string parent_name = null) { import dub.internal.utils : stripUTF8Bom; import dub.internal.vibecompat.core.file : openFile, FileMode; string text; { auto f = openFile(filename.toNativeString(), FileMode.read); scope(exit) f.close(); text = stripUTF8Bom(cast(string)f.readAll()); } return parsePackageRecipe(text, filename.toNativeString(), parent_name); } /** Parses an in-memory package recipe. The file format (JSON/SDLang) will be determined from the file extension. Params: contents = The contents of the recipe file filename = Name associated with the package recipe - this is only used to determine the file format from the file extension parent_name = Optional name of the parent package (if this is a sub package) default_package_name = Optional default package name (if no package name is found in the recipe this value will be used) Returns: Returns the package recipe contents Throws: Throws an exception if an I/O or syntax error occurs */ PackageRecipe parsePackageRecipe(string contents, string filename, string parent_name = null, string default_package_name = null) { import std.algorithm : endsWith; import dub.internal.vibecompat.data.json; import dub.recipe.json : parseJson; import dub.recipe.sdl : parseSDL; PackageRecipe ret; ret.name = default_package_name; if (filename.endsWith(".json")) parseJson(ret, parseJsonString(contents, filename), parent_name); else if (filename.endsWith(".sdl")) parseSDL(ret, contents, parent_name, filename); else assert(false, "readPackageRecipe called with filename with unknown extension: "~filename); return ret; } unittest { // issue #711 - configuration default target type not correct for SDL import dub.compilers.buildsettings : TargetType; auto inputs = [ "dub.sdl": "name \"test\"\nconfiguration \"a\" {\n}", "dub.json": "{\"name\": \"test\", \"configurations\": [{\"name\": \"a\"}]}" ]; foreach (file, content; inputs) { auto pr = parsePackageRecipe(content, file); assert(pr.name == "test"); assert(pr.configurations.length == 1); assert(pr.configurations[0].name == "a"); assert(pr.configurations[0].buildSettings.targetType == TargetType.library); } } unittest { // issue #711 - configuration default target type not correct for SDL import dub.compilers.buildsettings : TargetType; auto inputs = [ "dub.sdl": "name \"test\"\ntargetType \"autodetect\"\nconfiguration \"a\" {\n}", "dub.json": "{\"name\": \"test\", \"targetType\": \"autodetect\", \"configurations\": [{\"name\": \"a\"}]}" ]; foreach (file, content; inputs) { auto pr = parsePackageRecipe(content, file); assert(pr.name == "test"); assert(pr.configurations.length == 1); assert(pr.configurations[0].name == "a"); assert(pr.configurations[0].buildSettings.targetType == TargetType.library); } } unittest { // issue #711 - configuration default target type not correct for SDL import dub.compilers.buildsettings : TargetType; auto inputs = [ "dub.sdl": "name \"test\"\ntargetType \"executable\"\nconfiguration \"a\" {\n}", "dub.json": "{\"name\": \"test\", \"targetType\": \"executable\", \"configurations\": [{\"name\": \"a\"}]}" ]; foreach (file, content; inputs) { auto pr = parsePackageRecipe(content, file); assert(pr.name == "test"); assert(pr.configurations.length == 1); assert(pr.configurations[0].name == "a"); assert(pr.configurations[0].buildSettings.targetType == TargetType.executable); } } /** Writes the textual representation of a package recipe to a file. Note that the file extension must be either "json" or "sdl". */ void writePackageRecipe(string filename, in ref PackageRecipe recipe) { import dub.internal.vibecompat.core.file : openFile, FileMode; auto f = openFile(filename, FileMode.createTrunc); scope(exit) f.close(); serializePackageRecipe(f, recipe, filename); } /// ditto void writePackageRecipe(NativePath filename, in ref PackageRecipe recipe) { writePackageRecipe(filename.toNativeString, recipe); } /** Converts a package recipe to its textual representation. The extension of the supplied `filename` must be either "json" or "sdl". The output format is chosen accordingly. */ void serializePackageRecipe(R)(ref R dst, in ref PackageRecipe recipe, string filename) { import std.algorithm : endsWith; import dub.internal.vibecompat.data.json : writeJsonString; import dub.recipe.json : toJson; import dub.recipe.sdl : toSDL; if (filename.endsWith(".json")) dst.writeJsonString!(R, true)(toJson(recipe)); else if (filename.endsWith(".sdl")) toSDL(recipe).toSDLDocument(dst); else assert(false, "writePackageRecipe called with filename with unknown extension: "~filename); } dub-1.19.0/source/dub/recipe/json.d000066400000000000000000000324711360435400500170220ustar00rootroot00000000000000/** JSON format support for PackageRecipe Copyright: © 2012-2014 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig, Matthias Dondorff */ module dub.recipe.json; import dub.compilers.compiler; import dub.dependency; import dub.recipe.packagerecipe; import dub.internal.vibecompat.data.json; import std.algorithm : canFind, startsWith; import std.conv : to; import std.exception : enforce; import std.range; import std.string : format, indexOf; import std.traits : EnumMembers; void parseJson(ref PackageRecipe recipe, Json json, string parent_name) { foreach (string field, value; json) { switch (field) { default: break; case "name": recipe.name = value.get!string; break; case "version": recipe.version_ = value.get!string; break; case "description": recipe.description = value.get!string; break; case "homepage": recipe.homepage = value.get!string; break; case "authors": recipe.authors = deserializeJson!(string[])(value); break; case "copyright": recipe.copyright = value.get!string; break; case "license": recipe.license = value.get!string; break; case "configurations": break; // handled below, after the global settings have been parsed case "buildTypes": foreach (string name, settings; value) { BuildSettingsTemplate bs; bs.parseJson(settings, null); recipe.buildTypes[name] = bs; } break; case "toolchainRequirements": recipe.toolchainRequirements.parseJson(value); break; case "-ddoxFilterArgs": recipe.ddoxFilterArgs = deserializeJson!(string[])(value); break; case "-ddoxTool": recipe.ddoxTool = value.get!string; break; } } enforce(recipe.name.length > 0, "The package \"name\" field is missing or empty."); auto fullname = parent_name.length ? parent_name ~ ":" ~ recipe.name : recipe.name; // parse build settings recipe.buildSettings.parseJson(json, fullname); if (auto pv = "configurations" in json) { TargetType deftargettp = TargetType.library; if (recipe.buildSettings.targetType != TargetType.autodetect) deftargettp = recipe.buildSettings.targetType; foreach (settings; *pv) { ConfigurationInfo ci; ci.parseJson(settings, recipe.name, deftargettp); recipe.configurations ~= ci; } } // parse any sub packages after the main package has been fully parsed if (auto ps = "subPackages" in json) recipe.parseSubPackages(fullname, ps.opt!(Json[])); } Json toJson(in ref PackageRecipe recipe) { auto ret = recipe.buildSettings.toJson(); ret["name"] = recipe.name; if (!recipe.version_.empty) ret["version"] = recipe.version_; if (!recipe.description.empty) ret["description"] = recipe.description; if (!recipe.homepage.empty) ret["homepage"] = recipe.homepage; if (!recipe.authors.empty) ret["authors"] = serializeToJson(recipe.authors); if (!recipe.copyright.empty) ret["copyright"] = recipe.copyright; if (!recipe.license.empty) ret["license"] = recipe.license; if (!recipe.subPackages.empty) { Json[] jsonSubPackages = new Json[recipe.subPackages.length]; foreach (i, subPackage; recipe.subPackages) { if (subPackage.path !is null) { jsonSubPackages[i] = Json(subPackage.path); } else { jsonSubPackages[i] = subPackage.recipe.toJson(); } } ret["subPackages"] = jsonSubPackages; } if (recipe.configurations.length) { Json[] configs; foreach(config; recipe.configurations) configs ~= config.toJson(); ret["configurations"] = configs; } if (recipe.buildTypes.length) { Json[string] types; foreach (name, settings; recipe.buildTypes) types[name] = settings.toJson(); ret["buildTypes"] = types; } if (!recipe.toolchainRequirements.empty) { ret["toolchainRequirements"] = recipe.toolchainRequirements.toJson(); } if (!recipe.ddoxFilterArgs.empty) ret["-ddoxFilterArgs"] = recipe.ddoxFilterArgs.serializeToJson(); if (!recipe.ddoxTool.empty) ret["-ddoxTool"] = recipe.ddoxTool; return ret; } private void parseSubPackages(ref PackageRecipe recipe, string parent_package_name, Json[] subPackagesJson) { enforce(!parent_package_name.canFind(":"), format("'subPackages' found in '%s'. This is only supported in the main package file for '%s'.", parent_package_name, getBasePackageName(parent_package_name))); recipe.subPackages = new SubPackage[subPackagesJson.length]; foreach (i, subPackageJson; subPackagesJson) { // Handle referenced Packages if(subPackageJson.type == Json.Type.string) { string subpath = subPackageJson.get!string; recipe.subPackages[i] = SubPackage(subpath, PackageRecipe.init); } else { PackageRecipe subinfo; subinfo.parseJson(subPackageJson, parent_package_name); recipe.subPackages[i] = SubPackage(null, subinfo); } } } private void parseJson(ref ConfigurationInfo config, Json json, string package_name, TargetType default_target_type = TargetType.library) { config.buildSettings.targetType = default_target_type; foreach (string name, value; json) { switch (name) { default: break; case "name": config.name = value.get!string; enforce(!config.name.empty, "Configurations must have a non-empty name."); break; case "platforms": config.platforms = deserializeJson!(string[])(value); break; } } enforce(!config.name.empty, "Configuration is missing a name."); config.buildSettings.parseJson(json, package_name); } private Json toJson(in ref ConfigurationInfo config) { auto ret = config.buildSettings.toJson(); ret["name"] = config.name; if (config.platforms.length) ret["platforms"] = serializeToJson(config.platforms); return ret; } private void parseJson(ref BuildSettingsTemplate bs, Json json, string package_name) { foreach(string name, value; json) { auto idx = indexOf(name, "-"); string basename, suffix; if( idx >= 0 ) { basename = name[0 .. idx]; suffix = name[idx .. $]; } else basename = name; switch(basename){ default: break; case "dependencies": foreach (string pkg, verspec; value) { if (pkg.startsWith(":")) { enforce(!package_name.canFind(':'), format("Short-hand packages syntax not allowed within sub packages: %s -> %s", package_name, pkg)); pkg = package_name ~ pkg; } enforce(pkg !in bs.dependencies, "The dependency '"~pkg~"' is specified more than once." ); bs.dependencies[pkg] = deserializeJson!Dependency(verspec); } break; case "systemDependencies": bs.systemDependencies = value.get!string; break; case "targetType": enforce(suffix.empty, "targetType does not support platform customization."); bs.targetType = value.get!string.to!TargetType; break; case "targetPath": enforce(suffix.empty, "targetPath does not support platform customization."); bs.targetPath = value.get!string; break; case "targetName": enforce(suffix.empty, "targetName does not support platform customization."); bs.targetName = value.get!string; break; case "workingDirectory": enforce(suffix.empty, "workingDirectory does not support platform customization."); bs.workingDirectory = value.get!string; break; case "mainSourceFile": enforce(suffix.empty, "mainSourceFile does not support platform customization."); bs.mainSourceFile = value.get!string; break; case "subConfigurations": enforce(suffix.empty, "subConfigurations does not support platform customization."); bs.subConfigurations = deserializeJson!(string[string])(value); break; case "dflags": bs.dflags[suffix] = deserializeJson!(string[])(value); break; case "lflags": bs.lflags[suffix] = deserializeJson!(string[])(value); break; case "libs": bs.libs[suffix] = deserializeJson!(string[])(value); break; case "files": case "sourceFiles": bs.sourceFiles[suffix] = deserializeJson!(string[])(value); break; case "sourcePaths": bs.sourcePaths[suffix] = deserializeJson!(string[])(value); break; case "sourcePath": bs.sourcePaths[suffix] ~= [value.get!string]; break; // deprecated case "excludedSourceFiles": bs.excludedSourceFiles[suffix] = deserializeJson!(string[])(value); break; case "copyFiles": bs.copyFiles[suffix] = deserializeJson!(string[])(value); break; case "extraDependencyFiles": bs.extraDependencyFiles[suffix] = deserializeJson!(string[])(value); break; case "versions": bs.versions[suffix] = deserializeJson!(string[])(value); break; case "debugVersions": bs.debugVersions[suffix] = deserializeJson!(string[])(value); break; case "-versionFilters": bs.versionFilters[suffix] = deserializeJson!(string[])(value); break; case "-debugVersionFilters": bs.debugVersionFilters[suffix] = deserializeJson!(string[])(value); break; case "importPaths": bs.importPaths[suffix] = deserializeJson!(string[])(value); break; case "stringImportPaths": bs.stringImportPaths[suffix] = deserializeJson!(string[])(value); break; case "preGenerateCommands": bs.preGenerateCommands[suffix] = deserializeJson!(string[])(value); break; case "postGenerateCommands": bs.postGenerateCommands[suffix] = deserializeJson!(string[])(value); break; case "preBuildCommands": bs.preBuildCommands[suffix] = deserializeJson!(string[])(value); break; case "postBuildCommands": bs.postBuildCommands[suffix] = deserializeJson!(string[])(value); break; case "preRunCommands": bs.preRunCommands[suffix] = deserializeJson!(string[])(value); break; case "postRunCommands": bs.postRunCommands[suffix] = deserializeJson!(string[])(value); break; case "buildRequirements": BuildRequirements reqs; foreach (req; deserializeJson!(string[])(value)) reqs |= to!BuildRequirement(req); bs.buildRequirements[suffix] = reqs; break; case "buildOptions": BuildOptions options; foreach (opt; deserializeJson!(string[])(value)) options |= to!BuildOption(opt); bs.buildOptions[suffix] = options; break; } } } private Json toJson(in ref BuildSettingsTemplate bs) { auto ret = Json.emptyObject; if( bs.dependencies !is null ){ auto deps = Json.emptyObject; foreach( pack, d; bs.dependencies ) deps[pack] = serializeToJson(d); ret["dependencies"] = deps; } if (bs.systemDependencies !is null) ret["systemDependencies"] = bs.systemDependencies; if (bs.targetType != TargetType.autodetect) ret["targetType"] = bs.targetType.to!string(); if (!bs.targetPath.empty) ret["targetPath"] = bs.targetPath; if (!bs.targetName.empty) ret["targetName"] = bs.targetName; if (!bs.workingDirectory.empty) ret["workingDirectory"] = bs.workingDirectory; if (!bs.mainSourceFile.empty) ret["mainSourceFile"] = bs.mainSourceFile; if (bs.subConfigurations.length > 0) ret["subConfigurations"] = serializeToJson(bs.subConfigurations); foreach (suffix, arr; bs.dflags) ret["dflags"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.lflags) ret["lflags"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.libs) ret["libs"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.sourceFiles) ret["sourceFiles"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.sourcePaths) ret["sourcePaths"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.excludedSourceFiles) ret["excludedSourceFiles"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.copyFiles) ret["copyFiles"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.extraDependencyFiles) ret["extraDependencyFiles"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.versions) ret["versions"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.debugVersions) ret["debugVersions"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.versionFilters) ret["-versionFilters"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.debugVersionFilters) ret["-debugVersionFilters"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.importPaths) ret["importPaths"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.stringImportPaths) ret["stringImportPaths"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.preGenerateCommands) ret["preGenerateCommands"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.postGenerateCommands) ret["postGenerateCommands"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.preBuildCommands) ret["preBuildCommands"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.postBuildCommands) ret["postBuildCommands"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.preRunCommands) ret["preRunCommands"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.postRunCommands) ret["postRunCommands"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.buildRequirements) { string[] val; foreach (i; [EnumMembers!BuildRequirement]) if (arr & i) val ~= to!string(i); ret["buildRequirements"~suffix] = serializeToJson(val); } foreach (suffix, arr; bs.buildOptions) { string[] val; foreach (i; [EnumMembers!BuildOption]) if (arr & i) val ~= to!string(i); ret["buildOptions"~suffix] = serializeToJson(val); } return ret; } private void parseJson(ref ToolchainRequirements tr, Json json) { foreach (string name, value; json) tr.addRequirement(name, value.get!string); } private Json toJson(in ref ToolchainRequirements tr) { auto ret = Json.emptyObject; if (tr.dub != Dependency.any) ret["dub"] = serializeToJson(tr.dub); if (tr.frontend != Dependency.any) ret["frontend"] = serializeToJson(tr.frontend); if (tr.dmd != Dependency.any) ret["dmd"] = serializeToJson(tr.dmd); if (tr.ldc != Dependency.any) ret["ldc"] = serializeToJson(tr.ldc); if (tr.gdc != Dependency.any) ret["gdc"] = serializeToJson(tr.gdc); return ret; } dub-1.19.0/source/dub/recipe/packagerecipe.d000066400000000000000000000355671360435400500206450ustar00rootroot00000000000000/** Abstract representation of a package description file. Copyright: © 2012-2014 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig, Matthias Dondorff */ module dub.recipe.packagerecipe; import dub.compilers.compiler; import dub.compilers.utils : warnOnSpecialCompilerFlags; import dub.dependency; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.url; import std.algorithm : findSplit, sort; import std.array : join, split; import std.exception : enforce; import std.file; import std.range; import std.process : environment; /** Returns the individual parts of a qualified package name. Sub qualified package names are lists of package names separated by ":". For example, "packa:packb:packc" references a package named "packc" that is a sub package of "packb", which in turn is a sub package of "packa". */ string[] getSubPackagePath(string package_name) @safe pure { return package_name.split(":"); } /** Returns the name of the top level package for a given (sub) package name. In case of a top level package, the qualified name is returned unmodified. */ string getBasePackageName(string package_name) @safe pure { return package_name.findSplit(":")[0]; } /** Returns the qualified sub package part of the given package name. This is the part of the package name excluding the base package name. See also $(D getBasePackageName). */ string getSubPackageName(string package_name) @safe pure { return package_name.findSplit(":")[2]; } @safe unittest { assert(getSubPackagePath("packa:packb:packc") == ["packa", "packb", "packc"]); assert(getSubPackagePath("pack") == ["pack"]); assert(getBasePackageName("packa:packb:packc") == "packa"); assert(getBasePackageName("pack") == "pack"); assert(getSubPackageName("packa:packb:packc") == "packb:packc"); assert(getSubPackageName("pack") == ""); } /** Represents the contents of a package recipe file (dub.json/dub.sdl) in an abstract way. This structure is used to reason about package descriptions in isolation. For higher level package handling, see the $(D Package) class. */ struct PackageRecipe { string name; string version_; string description; string homepage; string[] authors; string copyright; string license; string[] ddoxFilterArgs; string ddoxTool; BuildSettingsTemplate buildSettings; ConfigurationInfo[] configurations; BuildSettingsTemplate[string] buildTypes; ToolchainRequirements toolchainRequirements; SubPackage[] subPackages; inout(ConfigurationInfo) getConfiguration(string name) inout { foreach (c; configurations) if (c.name == name) return c; throw new Exception("Unknown configuration: "~name); } /** Clones the package recipe recursively. */ PackageRecipe clone() const { return .clone(this); } } struct SubPackage { string path; PackageRecipe recipe; } /// Describes minimal toolchain requirements struct ToolchainRequirements { import std.typecons : Tuple, tuple; /// DUB version requirement Dependency dub = Dependency.any; /// D front-end version requirement Dependency frontend = Dependency.any; /// DMD version requirement Dependency dmd = Dependency.any; /// LDC version requirement Dependency ldc = Dependency.any; /// GDC version requirement Dependency gdc = Dependency.any; /** Get the list of supported compilers. Returns: An array of couples of compiler name and compiler requirement */ @property Tuple!(string, Dependency)[] supportedCompilers() const { Tuple!(string, Dependency)[] res; if (dmd != Dependency.invalid) res ~= Tuple!(string, Dependency)("dmd", dmd); if (ldc != Dependency.invalid) res ~= Tuple!(string, Dependency)("ldc", ldc); if (gdc != Dependency.invalid) res ~= Tuple!(string, Dependency)("gdc", gdc); return res; } bool empty() const { import std.algorithm.searching : all; return only(dub, frontend, dmd, ldc, gdc) .all!(r => r == Dependency.any); } } /// Bundles information about a build configuration. struct ConfigurationInfo { string name; string[] platforms; BuildSettingsTemplate buildSettings; this(string name, BuildSettingsTemplate build_settings) { enforce(!name.empty, "Configuration name is empty."); this.name = name; this.buildSettings = build_settings; } bool matchesPlatform(in BuildPlatform platform) const { if( platforms.empty ) return true; foreach(p; platforms) if( platform.matchesSpecification("-"~p) ) return true; return false; } } /// This keeps general information about how to build a package. /// It contains functions to create a specific BuildSetting, targeted at /// a certain BuildPlatform. struct BuildSettingsTemplate { Dependency[string] dependencies; string systemDependencies; TargetType targetType = TargetType.autodetect; string targetPath; string targetName; string workingDirectory; string mainSourceFile; string[string] subConfigurations; string[][string] dflags; string[][string] lflags; string[][string] libs; string[][string] sourceFiles; string[][string] sourcePaths; string[][string] excludedSourceFiles; string[][string] copyFiles; string[][string] extraDependencyFiles; string[][string] versions; string[][string] debugVersions; string[][string] versionFilters; string[][string] debugVersionFilters; string[][string] importPaths; string[][string] stringImportPaths; string[][string] preGenerateCommands; string[][string] postGenerateCommands; string[][string] preBuildCommands; string[][string] postBuildCommands; string[][string] preRunCommands; string[][string] postRunCommands; BuildRequirements[string] buildRequirements; BuildOptions[string] buildOptions; /// Constructs a BuildSettings object from this template. void getPlatformSettings(ref BuildSettings dst, in BuildPlatform platform, NativePath base_path) const { dst.targetType = this.targetType; if (!this.targetPath.empty) dst.targetPath = this.targetPath; if (!this.targetName.empty) dst.targetName = this.targetName; if (!this.workingDirectory.empty) dst.workingDirectory = this.workingDirectory; if (!this.mainSourceFile.empty) { auto p = NativePath(this.mainSourceFile); p.normalize(); dst.mainSourceFile = p.toNativeString(); dst.addSourceFiles(dst.mainSourceFile); } string[] collectFiles(in string[][string] paths_map, string pattern) { auto files = appender!(string[]); import dub.project : buildSettingsVars; import std.typecons : Nullable; static Nullable!(string[string]) envVarCache; if (envVarCache.isNull) envVarCache = environment.toAA(); foreach (suffix, paths; paths_map) { if (!platform.matchesSpecification(suffix)) continue; foreach (spath; paths) { enforce(!spath.empty, "Paths must not be empty strings."); auto path = NativePath(spath); if (!path.absolute) path = base_path ~ path; if (!existsFile(path) || !isDir(path.toNativeString())) { import std.algorithm : any, find; const hasVar = chain(buildSettingsVars, envVarCache.get.byKey).any!((string var) { return spath.find("$"~var).length > 0 || spath.find("${"~var~"}").length > 0; }); if (!hasVar) logWarn("Invalid source/import path: %s", path.toNativeString()); continue; } foreach (d; dirEntries(path.toNativeString(), pattern, SpanMode.depth)) { import std.path : baseName; if (baseName(d.name)[0] == '.' || d.isDir) continue; auto src = NativePath(d.name).relativeTo(base_path); files ~= src.toNativeString(); } } } return files.data; } // collect source files dst.addSourceFiles(collectFiles(sourcePaths, "*.d")); auto sourceFiles = dst.sourceFiles.sort(); // collect import files and remove sources import std.algorithm : copy, setDifference; auto importFiles = collectFiles(importPaths, "*.{d,di}").sort(); immutable nremoved = importFiles.setDifference(sourceFiles).copy(importFiles.release).length; importFiles = importFiles[0 .. $ - nremoved]; dst.addImportFiles(importFiles.release); dst.addStringImportFiles(collectFiles(stringImportPaths, "*")); getPlatformSetting!("dflags", "addDFlags")(dst, platform); getPlatformSetting!("lflags", "addLFlags")(dst, platform); getPlatformSetting!("libs", "addLibs")(dst, platform); getPlatformSetting!("sourceFiles", "addSourceFiles")(dst, platform); getPlatformSetting!("excludedSourceFiles", "removeSourceFiles")(dst, platform); getPlatformSetting!("copyFiles", "addCopyFiles")(dst, platform); getPlatformSetting!("extraDependencyFiles", "addExtraDependencyFiles")(dst, platform); getPlatformSetting!("versions", "addVersions")(dst, platform); getPlatformSetting!("debugVersions", "addDebugVersions")(dst, platform); getPlatformSetting!("versionFilters", "addVersionFilters")(dst, platform); getPlatformSetting!("debugVersionFilters", "addDebugVersionFilters")(dst, platform); getPlatformSetting!("importPaths", "addImportPaths")(dst, platform); getPlatformSetting!("stringImportPaths", "addStringImportPaths")(dst, platform); getPlatformSetting!("preGenerateCommands", "addPreGenerateCommands")(dst, platform); getPlatformSetting!("postGenerateCommands", "addPostGenerateCommands")(dst, platform); getPlatformSetting!("preBuildCommands", "addPreBuildCommands")(dst, platform); getPlatformSetting!("postBuildCommands", "addPostBuildCommands")(dst, platform); getPlatformSetting!("preRunCommands", "addPreRunCommands")(dst, platform); getPlatformSetting!("postRunCommands", "addPostRunCommands")(dst, platform); getPlatformSetting!("buildRequirements", "addRequirements")(dst, platform); getPlatformSetting!("buildOptions", "addOptions")(dst, platform); } void getPlatformSetting(string name, string addname)(ref BuildSettings dst, in BuildPlatform platform) const { foreach(suffix, values; __traits(getMember, this, name)){ if( platform.matchesSpecification(suffix) ) __traits(getMember, dst, addname)(values); } } void warnOnSpecialCompilerFlags(string package_name, string config_name) { auto nodef = false; auto noprop = false; foreach (req; this.buildRequirements) { if (req & BuildRequirement.noDefaultFlags) nodef = true; if (req & BuildRequirement.relaxProperties) noprop = true; } if (noprop) { logWarn(`Warning: "buildRequirements": ["relaxProperties"] is deprecated and is now the default behavior. Note that the -property switch will probably be removed in future versions of DMD.`); logWarn(""); } if (nodef) { logWarn("Warning: This package uses the \"noDefaultFlags\" build requirement. Please use only for development purposes and not for released packages."); logWarn(""); } else { string[] all_dflags; BuildOptions all_options; foreach (flags; this.dflags) all_dflags ~= flags; foreach (options; this.buildOptions) all_options |= options; .warnOnSpecialCompilerFlags(all_dflags, all_options, package_name, config_name); } } } package(dub) void checkPlatform(in ref ToolchainRequirements tr, BuildPlatform platform, string package_name) { import dub.compilers.utils : dmdLikeVersionToSemverLike; import std.algorithm.iteration : map; import std.format : format; string compilerver; Dependency compilerspec; switch (platform.compiler) { default: compilerspec = Dependency.any; compilerver = "0.0.0"; break; case "dmd": compilerspec = tr.dmd; compilerver = platform.compilerVersion.length ? dmdLikeVersionToSemverLike(platform.compilerVersion) : "0.0.0"; break; case "ldc": compilerspec = tr.ldc; compilerver = platform.compilerVersion; if (!compilerver.length) compilerver = "0.0.0"; break; case "gdc": compilerspec = tr.gdc; compilerver = platform.compilerVersion; if (!compilerver.length) compilerver = "0.0.0"; break; } enforce(compilerspec != Dependency.invalid, format( "Installed %s %s is not supported by %s. Supported compiler(s):\n%s", platform.compiler, platform.compilerVersion, package_name, tr.supportedCompilers.map!((cs) { auto str = " - " ~ cs[0]; if (cs[1] != Dependency.any) str ~= ": " ~ cs[1].toString(); return str; }).join("\n") ) ); enforce(compilerspec.matches(compilerver), format( "Installed %s-%s does not comply with %s compiler requirement: %s %s\n" ~ "Please consider upgrading your installation.", platform.compiler, platform.compilerVersion, package_name, platform.compiler, compilerspec ) ); enforce(tr.frontend.matches(dmdLikeVersionToSemverLike(platform.frontendVersionString)), format( "Installed %s-%s with frontend %s does not comply with %s frontend requirement: %s\n" ~ "Please consider upgrading your installation.", platform.compiler, platform.compilerVersion, platform.frontendVersionString, package_name, tr.frontend ) ); } package bool addRequirement(ref ToolchainRequirements req, string name, string value) { switch (name) { default: return false; case "dub": req.dub = parseDependency(value); break; case "frontend": req.frontend = parseDMDDependency(value); break; case "ldc": req.ldc = parseDependency(value); break; case "gdc": req.gdc = parseDependency(value); break; case "dmd": req.dmd = parseDMDDependency(value); break; } return true; } private static Dependency parseDependency(string dep) { if (dep == "no") return Dependency.invalid; return Dependency(dep); } private static Dependency parseDMDDependency(string dep) { import dub.compilers.utils : dmdLikeVersionToSemverLike; import dub.dependency : Dependency; import std.algorithm : map, splitter; import std.array : join; if (dep == "no") return Dependency.invalid; return dep .splitter(' ') .map!(r => dmdLikeVersionToSemverLike(r)) .join(' ') .Dependency; } private T clone(T)(ref const(T) val) { import std.traits : isSomeString, isDynamicArray, isAssociativeArray, isBasicType, ValueType; static if (is(T == immutable)) return val; else static if (isBasicType!T) return val; else static if (isDynamicArray!T) { alias V = typeof(T.init[0]); static if (is(V == immutable)) return val; else { T ret = new V[val.length]; foreach (i, ref f; val) ret[i] = clone!V(f); return ret; } } else static if (isAssociativeArray!T) { alias V = ValueType!T; T ret; foreach (k, ref f; val) ret[k] = clone!V(f); return ret; } else static if (is(T == struct)) { T ret; foreach (i, M; typeof(T.tupleof)) ret.tupleof[i] = clone!M(val.tupleof[i]); return ret; } else static assert(false, "Unsupported type: "~T.stringof); } unittest { // issue #1407 - duplicate main source file { BuildSettingsTemplate t; t.mainSourceFile = "./foo.d"; t.sourceFiles[""] = ["foo.d"]; BuildSettings bs; t.getPlatformSettings(bs, BuildPlatform.init, NativePath("/")); assert(bs.sourceFiles == ["foo.d"]); } version (Windows) {{ BuildSettingsTemplate t; t.mainSourceFile = "src/foo.d"; t.sourceFiles[""] = ["src\\foo.d"]; BuildSettings bs; t.getPlatformSettings(bs, BuildPlatform.init, NativePath("/")); assert(bs.sourceFiles == ["src\\foo.d"]); }} } dub-1.19.0/source/dub/recipe/sdl.d000066400000000000000000000603221360435400500166270ustar00rootroot00000000000000/** SDL format support for PackageRecipe Copyright: © 2014-2015 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.recipe.sdl; import dub.compilers.compiler; import dub.dependency; import dub.internal.sdlang; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import dub.recipe.packagerecipe; import std.algorithm : map; import std.array : array; import std.conv; import std.string : startsWith; void parseSDL(ref PackageRecipe recipe, string sdl, string parent_name, string filename) { parseSDL(recipe, parseSource(sdl, filename), parent_name); } void parseSDL(ref PackageRecipe recipe, Tag sdl, string parent_name) { Tag[] subpacks; Tag[] configs; // parse top-level fields foreach (n; sdl.all.tags) { enforceSDL(n.name.length > 0, "Anonymous tags are not allowed at the root level.", n); switch (n.fullName) { default: break; case "name": recipe.name = n.stringTagValue; break; case "version": recipe.version_ = n.stringTagValue; break; case "description": recipe.description = n.stringTagValue; break; case "homepage": recipe.homepage = n.stringTagValue; break; case "authors": recipe.authors ~= n.stringArrayTagValue; break; case "copyright": recipe.copyright = n.stringTagValue; break; case "license": recipe.license = n.stringTagValue; break; case "subPackage": subpacks ~= n; break; case "configuration": configs ~= n; break; case "buildType": auto name = n.stringTagValue(true); BuildSettingsTemplate bt; parseBuildSettings(n, bt, parent_name); recipe.buildTypes[name] = bt; break; case "toolchainRequirements": parseToolchainRequirements(recipe.toolchainRequirements, n); break; case "x:ddoxFilterArgs": recipe.ddoxFilterArgs ~= n.stringArrayTagValue; break; case "x:ddoxTool": recipe.ddoxTool = n.stringTagValue; break; } } enforceSDL(recipe.name.length > 0, "The package \"name\" field is missing or empty.", sdl); string full_name = parent_name.length ? parent_name ~ ":" ~ recipe.name : recipe.name; // parse general build settings parseBuildSettings(sdl, recipe.buildSettings, full_name); // determine default target type for configurations auto defttype = recipe.buildSettings.targetType; if (defttype == TargetType.autodetect) defttype = TargetType.library; // parse configurations recipe.configurations.length = configs.length; foreach (i, n; configs) { recipe.configurations[i].buildSettings.targetType = defttype; parseConfiguration(n, recipe.configurations[i], full_name); } // finally parse all sub packages recipe.subPackages.length = subpacks.length; foreach (i, n; subpacks) { if (n.values.length) { recipe.subPackages[i].path = n.stringTagValue; } else { enforceSDL(n.attributes.length == 0, "No attributes allowed for inline sub package definitions.", n); parseSDL(recipe.subPackages[i].recipe, n, full_name); } } } Tag toSDL(in ref PackageRecipe recipe) { Tag ret = new Tag; void add(T)(string field, T value) { ret.add(new Tag(null, field, [Value(value)])); } add("name", recipe.name); if (recipe.version_.length) add("version", recipe.version_); if (recipe.description.length) add("description", recipe.description); if (recipe.homepage.length) add("homepage", recipe.homepage); if (recipe.authors.length) ret.add(new Tag(null, "authors", recipe.authors.map!(a => Value(a)).array)); if (recipe.copyright.length) add("copyright", recipe.copyright); if (recipe.license.length) add("license", recipe.license); foreach (name, settings; recipe.buildTypes) { auto t = new Tag(null, "buildType", [Value(name)]); t.add(settings.toSDL()); ret.add(t); } if (!recipe.toolchainRequirements.empty) { ret.add(toSDL(recipe.toolchainRequirements)); } if (recipe.ddoxFilterArgs.length) ret.add(new Tag("x", "ddoxFilterArgs", recipe.ddoxFilterArgs.map!(a => Value(a)).array)); if (recipe.ddoxTool.length) ret.add(new Tag("x", "ddoxTool", [Value(recipe.ddoxTool)])); ret.add(recipe.buildSettings.toSDL()); foreach(config; recipe.configurations) ret.add(config.toSDL()); foreach (i, subPackage; recipe.subPackages) { if (subPackage.path !is null) { add("subPackage", subPackage.path); } else { auto t = subPackage.recipe.toSDL(); t.name = "subPackage"; ret.add(t); } } return ret; } private void parseBuildSettings(Tag settings, ref BuildSettingsTemplate bs, string package_name) { foreach (setting; settings.all.tags) parseBuildSetting(setting, bs, package_name); } private void parseBuildSetting(Tag setting, ref BuildSettingsTemplate bs, string package_name) { switch (setting.fullName) { default: break; case "dependency": parseDependency(setting, bs, package_name); break; case "systemDependencies": bs.systemDependencies = setting.stringTagValue; break; case "targetType": bs.targetType = setting.stringTagValue.to!TargetType; break; case "targetName": bs.targetName = setting.stringTagValue; break; case "targetPath": bs.targetPath = setting.stringTagValue; break; case "workingDirectory": bs.workingDirectory = setting.stringTagValue; break; case "subConfiguration": auto args = setting.stringArrayTagValue; enforceSDL(args.length == 2, "Expecting package and configuration names as arguments.", setting); bs.subConfigurations[expandPackageName(args[0], package_name, setting)] = args[1]; break; case "dflags": setting.parsePlatformStringArray(bs.dflags); break; case "lflags": setting.parsePlatformStringArray(bs.lflags); break; case "libs": setting.parsePlatformStringArray(bs.libs); break; case "sourceFiles": setting.parsePlatformStringArray(bs.sourceFiles); break; case "sourcePaths": setting.parsePlatformStringArray(bs.sourcePaths); break; case "excludedSourceFiles": setting.parsePlatformStringArray(bs.excludedSourceFiles); break; case "mainSourceFile": bs.mainSourceFile = setting.stringTagValue; break; case "copyFiles": setting.parsePlatformStringArray(bs.copyFiles); break; case "extraDependencyFiles": setting.parsePlatformStringArray(bs.extraDependencyFiles); break; case "versions": setting.parsePlatformStringArray(bs.versions); break; case "debugVersions": setting.parsePlatformStringArray(bs.debugVersions); break; case "x:versionFilters": setting.parsePlatformStringArray(bs.versionFilters); break; case "x:debugVersionFilters": setting.parsePlatformStringArray(bs.debugVersionFilters); break; case "importPaths": setting.parsePlatformStringArray(bs.importPaths); break; case "stringImportPaths": setting.parsePlatformStringArray(bs.stringImportPaths); break; case "preGenerateCommands": setting.parsePlatformStringArray(bs.preGenerateCommands); break; case "postGenerateCommands": setting.parsePlatformStringArray(bs.postGenerateCommands); break; case "preBuildCommands": setting.parsePlatformStringArray(bs.preBuildCommands); break; case "postBuildCommands": setting.parsePlatformStringArray(bs.postBuildCommands); break; case "preRunCommands": setting.parsePlatformStringArray(bs.preRunCommands); break; case "postRunCommands": setting.parsePlatformStringArray(bs.postRunCommands); break; case "buildRequirements": setting.parsePlatformEnumArray!BuildRequirement(bs.buildRequirements); break; case "buildOptions": setting.parsePlatformEnumArray!BuildOption(bs.buildOptions); break; } } private void parseDependency(Tag t, ref BuildSettingsTemplate bs, string package_name) { enforceSDL(t.values.length != 0, "Missing dependency name.", t); enforceSDL(t.values.length == 1, "Multiple dependency names.", t); auto pkg = expandPackageName(t.values[0].get!string, package_name, t); enforceSDL(pkg !in bs.dependencies, "The dependency '"~pkg~"' is specified more than once.", t); Dependency dep = Dependency.any; auto attrs = t.attributes; if ("path" in attrs) { if ("version" in attrs) logDiagnostic("Ignoring version specification (%s) for path based dependency %s", attrs["version"][0].value.get!string, attrs["path"][0].value.get!string); dep.versionSpec = "*"; dep.path = NativePath(attrs["path"][0].value.get!string); } else { enforceSDL("version" in attrs, "Missing version specification.", t); dep.versionSpec = attrs["version"][0].value.get!string; } if ("optional" in attrs) dep.optional = attrs["optional"][0].value.get!bool; if ("default" in attrs) dep.default_ = attrs["default"][0].value.get!bool; bs.dependencies[pkg] = dep; } private void parseConfiguration(Tag t, ref ConfigurationInfo ret, string package_name) { ret.name = t.stringTagValue(true); foreach (f; t.tags) { switch (f.fullName) { default: parseBuildSetting(f, ret.buildSettings, package_name); break; case "platforms": ret.platforms ~= f.stringArrayTagValue; break; } } } private Tag toSDL(in ref ConfigurationInfo config) { auto ret = new Tag(null, "configuration", [Value(config.name)]); if (config.platforms.length) ret.add(new Tag(null, "platforms", config.platforms[].map!(p => Value(p)).array)); ret.add(config.buildSettings.toSDL()); return ret; } private Tag[] toSDL(in ref BuildSettingsTemplate bs) { Tag[] ret; void add(string name, string value, string namespace = null) { ret ~= new Tag(namespace, name, [Value(value)]); } void adda(string name, string suffix, in string[] values, string namespace = null) { ret ~= new Tag(namespace, name, values[].map!(v => Value(v)).array, suffix.length ? [new Attribute(null, "platform", Value(suffix[1 .. $]))] : null); } string[] toNameArray(T, U)(U bits) if(is(T == enum)) { string[] ret; foreach (m; __traits(allMembers, T)) if (bits & __traits(getMember, T, m)) ret ~= m; return ret; } foreach (pack, d; bs.dependencies) { Attribute[] attribs; if (!d.path.empty) attribs ~= new Attribute(null, "path", Value(d.path.toString())); else attribs ~= new Attribute(null, "version", Value(d.versionSpec)); if (d.optional) attribs ~= new Attribute(null, "optional", Value(true)); ret ~= new Tag(null, "dependency", [Value(pack)], attribs); } if (bs.systemDependencies !is null) add("systemDependencies", bs.systemDependencies); if (bs.targetType != TargetType.autodetect) add("targetType", bs.targetType.to!string()); if (bs.targetPath.length) add("targetPath", bs.targetPath); if (bs.targetName.length) add("targetName", bs.targetName); if (bs.workingDirectory.length) add("workingDirectory", bs.workingDirectory); if (bs.mainSourceFile.length) add("mainSourceFile", bs.mainSourceFile); foreach (pack, conf; bs.subConfigurations) ret ~= new Tag(null, "subConfiguration", [Value(pack), Value(conf)]); foreach (suffix, arr; bs.dflags) adda("dflags", suffix, arr); foreach (suffix, arr; bs.lflags) adda("lflags", suffix, arr); foreach (suffix, arr; bs.libs) adda("libs", suffix, arr); foreach (suffix, arr; bs.sourceFiles) adda("sourceFiles", suffix, arr); foreach (suffix, arr; bs.sourcePaths) adda("sourcePaths", suffix, arr); foreach (suffix, arr; bs.excludedSourceFiles) adda("excludedSourceFiles", suffix, arr); foreach (suffix, arr; bs.copyFiles) adda("copyFiles", suffix, arr); foreach (suffix, arr; bs.extraDependencyFiles) adda("extraDependencyFiles", suffix, arr); foreach (suffix, arr; bs.versions) adda("versions", suffix, arr); foreach (suffix, arr; bs.debugVersions) adda("debugVersions", suffix, arr); foreach (suffix, arr; bs.versionFilters) adda("versionFilters", suffix, arr, "x"); foreach (suffix, arr; bs.debugVersionFilters) adda("debugVersionFilters", suffix, arr, "x"); foreach (suffix, arr; bs.importPaths) adda("importPaths", suffix, arr); foreach (suffix, arr; bs.stringImportPaths) adda("stringImportPaths", suffix, arr); foreach (suffix, arr; bs.preGenerateCommands) adda("preGenerateCommands", suffix, arr); foreach (suffix, arr; bs.postGenerateCommands) adda("postGenerateCommands", suffix, arr); foreach (suffix, arr; bs.preBuildCommands) adda("preBuildCommands", suffix, arr); foreach (suffix, arr; bs.postBuildCommands) adda("postBuildCommands", suffix, arr); foreach (suffix, arr; bs.preRunCommands) adda("preRunCommands", suffix, arr); foreach (suffix, arr; bs.postRunCommands) adda("postRunCommands", suffix, arr); foreach (suffix, bits; bs.buildRequirements) adda("buildRequirements", suffix, toNameArray!BuildRequirement(bits)); foreach (suffix, bits; bs.buildOptions) adda("buildOptions", suffix, toNameArray!BuildOption(bits)); return ret; } private void parseToolchainRequirements(ref ToolchainRequirements tr, Tag tag) { foreach (attr; tag.attributes) tr.addRequirement(attr.name, attr.value.get!string); } private Tag toSDL(const ref ToolchainRequirements tr) { Attribute[] attrs; if (tr.dub != Dependency.any) attrs ~= new Attribute("dub", Value(tr.dub.toString())); if (tr.frontend != Dependency.any) attrs ~= new Attribute("frontend", Value(tr.frontend.toString())); if (tr.dmd != Dependency.any) attrs ~= new Attribute("dmd", Value(tr.dmd.toString())); if (tr.ldc != Dependency.any) attrs ~= new Attribute("ldc", Value(tr.ldc.toString())); if (tr.gdc != Dependency.any) attrs ~= new Attribute("gdc", Value(tr.gdc.toString())); return new Tag(null, "toolchainRequirements", null, attrs); } private string expandPackageName(string name, string parent_name, Tag tag) { import std.algorithm : canFind; import std.string : format; if (name.startsWith(":")) { enforceSDL(!parent_name.canFind(':'), format("Short-hand packages syntax not allowed within sub packages: %s -> %s", parent_name, name), tag); return parent_name ~ name; } else return name; } private string stringTagValue(Tag t, bool allow_child_tags = false) { import std.string : format; enforceSDL(t.values.length > 0, format("Missing string value for '%s'.", t.fullName), t); enforceSDL(t.values.length == 1, format("Expected only one value for '%s'.", t.fullName), t); enforceSDL(t.values[0].peek!string !is null, format("Expected value of type string for '%s'.", t.fullName), t); enforceSDL(allow_child_tags || t.tags.length == 0, format("No child tags allowed for '%s'.", t.fullName), t); // Q: should attributes be disallowed, or just ignored for forward compatibility reasons? //enforceSDL(t.attributes.length == 0, format("No attributes allowed for '%s'.", t.fullName), t); return t.values[0].get!string; } private string[] stringArrayTagValue(Tag t, bool allow_child_tags = false) { import std.string : format; enforceSDL(allow_child_tags || t.tags.length == 0, format("No child tags allowed for '%s'.", t.fullName), t); // Q: should attributes be disallowed, or just ignored for forward compatibility reasons? //enforceSDL(t.attributes.length == 0, format("No attributes allowed for '%s'.", t.fullName), t); string[] ret; foreach (v; t.values) { enforceSDL(t.values[0].peek!string !is null, format("Values for '%s' must be strings.", t.fullName), t); ret ~= v.get!string; } return ret; } private void parsePlatformStringArray(Tag t, ref string[][string] dst) { string platform; if ("platform" in t.attributes) platform = "-" ~ t.attributes["platform"][0].value.get!string; dst[platform] ~= t.values.map!(v => v.get!string).array; } private void parsePlatformEnumArray(E, Es)(Tag t, ref Es[string] dst) { string platform; if ("platform" in t.attributes) platform = "-" ~ t.attributes["platform"][0].value.get!string; foreach (v; t.values) { if (platform !in dst) dst[platform] = Es.init; dst[platform] |= v.get!string.to!E; } } private void enforceSDL(bool condition, lazy string message, Tag tag, string file = __FILE__, int line = __LINE__) { import std.string : format; if (!condition) { throw new Exception(format("%s(%s): Error: %s", tag.location.file, tag.location.line + 1, message), file, line); } } unittest { // test all possible fields auto sdl = `name "projectname"; description "project description"; homepage "http://example.com" authors "author 1" "author 2" authors "author 3" copyright "copyright string" license "license string" version "1.0.0" subPackage { name "subpackage1" } subPackage { name "subpackage2" dependency "projectname:subpackage1" version="*" } subPackage "pathsp3" configuration "config1" { platforms "windows" "linux" targetType "library" } configuration "config2" { platforms "windows-x86" targetType "executable" } buildType "debug" { dflags "-g" "-debug" } buildType "release" { dflags "-release" "-O" } toolchainRequirements dub="~>1.11.0" dmd="~>2.082" x:ddoxFilterArgs "-arg1" "-arg2" x:ddoxFilterArgs "-arg3" x:ddoxTool "ddoxtool" dependency ":subpackage1" optional=false path="." dependency "somedep" version="1.0.0" optional=true systemDependencies "system dependencies" targetType "executable" targetName "target name" targetPath "target path" workingDirectory "working directory" subConfiguration ":subpackage2" "library" buildRequirements "allowWarnings" "silenceDeprecations" buildOptions "verbose" "ignoreUnknownPragmas" libs "lib1" "lib2" libs "lib3" sourceFiles "source1" "source2" sourceFiles "source3" sourcePaths "sourcepath1" "sourcepath2" sourcePaths "sourcepath3" excludedSourceFiles "excluded1" "excluded2" excludedSourceFiles "excluded3" mainSourceFile "main source" copyFiles "copy1" "copy2" copyFiles "copy3" extraDependencyFiles "extradepfile1" "extradepfile2" extraDependencyFiles "extradepfile3" versions "version1" "version2" versions "version3" debugVersions "debug1" "debug2" debugVersions "debug3" x:versionFilters "version1" "version2" x:versionFilters "version3" x:versionFilters x:debugVersionFilters "debug1" "debug2" x:debugVersionFilters "debug3" x:debugVersionFilters importPaths "import1" "import2" importPaths "import3" stringImportPaths "string1" "string2" stringImportPaths "string3" preGenerateCommands "preg1" "preg2" preGenerateCommands "preg3" postGenerateCommands "postg1" "postg2" postGenerateCommands "postg3" preBuildCommands "preb1" "preb2" preBuildCommands "preb3" postBuildCommands "postb1" "postb2" postBuildCommands "postb3" preRunCommands "prer1" "prer2" preRunCommands "prer3" postRunCommands "postr1" "postr2" postRunCommands "postr3" dflags "df1" "df2" dflags "df3" lflags "lf1" "lf2" lflags "lf3" `; PackageRecipe rec1; parseSDL(rec1, sdl, null, "testfile"); PackageRecipe rec; parseSDL(rec, rec1.toSDL(), null); // verify that all fields are serialized properly assert(rec.name == "projectname"); assert(rec.description == "project description"); assert(rec.homepage == "http://example.com"); assert(rec.authors == ["author 1", "author 2", "author 3"]); assert(rec.copyright == "copyright string"); assert(rec.license == "license string"); assert(rec.version_ == "1.0.0"); assert(rec.subPackages.length == 3); assert(rec.subPackages[0].path == ""); assert(rec.subPackages[0].recipe.name == "subpackage1"); assert(rec.subPackages[1].path == ""); assert(rec.subPackages[1].recipe.name == "subpackage2"); assert(rec.subPackages[1].recipe.buildSettings.dependencies.length == 1); assert("projectname:subpackage1" in rec.subPackages[1].recipe.buildSettings.dependencies); assert(rec.subPackages[2].path == "pathsp3"); assert(rec.configurations.length == 2); assert(rec.configurations[0].name == "config1"); assert(rec.configurations[0].platforms == ["windows", "linux"]); assert(rec.configurations[0].buildSettings.targetType == TargetType.library); assert(rec.configurations[1].name == "config2"); assert(rec.configurations[1].platforms == ["windows-x86"]); assert(rec.configurations[1].buildSettings.targetType == TargetType.executable); assert(rec.buildTypes.length == 2); assert(rec.buildTypes["debug"].dflags == ["": ["-g", "-debug"]]); assert(rec.buildTypes["release"].dflags == ["": ["-release", "-O"]]); assert(rec.toolchainRequirements.dub == Dependency("~>1.11.0")); assert(rec.toolchainRequirements.frontend == Dependency.any); assert(rec.toolchainRequirements.dmd == Dependency("~>2.82.0")); assert(rec.toolchainRequirements.ldc == Dependency.any); assert(rec.toolchainRequirements.gdc == Dependency.any); assert(rec.ddoxFilterArgs == ["-arg1", "-arg2", "-arg3"], rec.ddoxFilterArgs.to!string); assert(rec.ddoxTool == "ddoxtool"); assert(rec.buildSettings.dependencies.length == 2); assert(rec.buildSettings.dependencies["projectname:subpackage1"].optional == false); assert(rec.buildSettings.dependencies["projectname:subpackage1"].path == NativePath(".")); assert(rec.buildSettings.dependencies["somedep"].versionSpec == "1.0.0"); assert(rec.buildSettings.dependencies["somedep"].optional == true); assert(rec.buildSettings.dependencies["somedep"].path.empty); assert(rec.buildSettings.systemDependencies == "system dependencies"); assert(rec.buildSettings.targetType == TargetType.executable); assert(rec.buildSettings.targetName == "target name"); assert(rec.buildSettings.targetPath == "target path"); assert(rec.buildSettings.workingDirectory == "working directory"); assert(rec.buildSettings.subConfigurations.length == 1); assert(rec.buildSettings.subConfigurations["projectname:subpackage2"] == "library"); assert(rec.buildSettings.buildRequirements == ["": cast(BuildRequirements)(BuildRequirement.allowWarnings | BuildRequirement.silenceDeprecations)]); assert(rec.buildSettings.buildOptions == ["": cast(BuildOptions)(BuildOption.verbose | BuildOption.ignoreUnknownPragmas)]); assert(rec.buildSettings.libs == ["": ["lib1", "lib2", "lib3"]]); assert(rec.buildSettings.sourceFiles == ["": ["source1", "source2", "source3"]]); assert(rec.buildSettings.sourcePaths == ["": ["sourcepath1", "sourcepath2", "sourcepath3"]]); assert(rec.buildSettings.excludedSourceFiles == ["": ["excluded1", "excluded2", "excluded3"]]); assert(rec.buildSettings.mainSourceFile == "main source"); assert(rec.buildSettings.copyFiles == ["": ["copy1", "copy2", "copy3"]]); assert(rec.buildSettings.extraDependencyFiles == ["": ["extradepfile1", "extradepfile2", "extradepfile3"]]); assert(rec.buildSettings.versions == ["": ["version1", "version2", "version3"]]); assert(rec.buildSettings.debugVersions == ["": ["debug1", "debug2", "debug3"]]); assert(rec.buildSettings.versionFilters == ["": ["version1", "version2", "version3"]]); assert(rec.buildSettings.debugVersionFilters == ["": ["debug1", "debug2", "debug3"]]); assert(rec.buildSettings.importPaths == ["": ["import1", "import2", "import3"]]); assert(rec.buildSettings.stringImportPaths == ["": ["string1", "string2", "string3"]]); assert(rec.buildSettings.preGenerateCommands == ["": ["preg1", "preg2", "preg3"]]); assert(rec.buildSettings.postGenerateCommands == ["": ["postg1", "postg2", "postg3"]]); assert(rec.buildSettings.preBuildCommands == ["": ["preb1", "preb2", "preb3"]]); assert(rec.buildSettings.postBuildCommands == ["": ["postb1", "postb2", "postb3"]]); assert(rec.buildSettings.preRunCommands == ["": ["prer1", "prer2", "prer3"]]); assert(rec.buildSettings.postRunCommands == ["": ["postr1", "postr2", "postr3"]]); assert(rec.buildSettings.dflags == ["": ["df1", "df2", "df3"]]); assert(rec.buildSettings.lflags == ["": ["lf1", "lf2", "lf3"]]); } unittest { // test platform identifiers auto sdl = `name "testproject" dflags "-a" "-b" platform="windows-x86" dflags "-c" platform="windows-x86" dflags "-e" "-f" dflags "-g" dflags "-h" "-i" platform="linux" dflags "-j" platform="linux" `; PackageRecipe rec; parseSDL(rec, sdl, null, "testfile"); assert(rec.buildSettings.dflags.length == 3); assert(rec.buildSettings.dflags["-windows-x86"] == ["-a", "-b", "-c"]); assert(rec.buildSettings.dflags[""] == ["-e", "-f", "-g"]); assert(rec.buildSettings.dflags["-linux"] == ["-h", "-i", "-j"]); } unittest { // test for missing name field import std.exception; auto sdl = `description "missing name"`; PackageRecipe rec; assertThrown(parseSDL(rec, sdl, null, "testfile")); } unittest { // test single value fields import std.exception; PackageRecipe rec; assertThrown!Exception(parseSDL(rec, `name "hello" "world"`, null, "testfile")); assertThrown!Exception(parseSDL(rec, `name`, null, "testfile")); assertThrown!Exception(parseSDL(rec, `name 10`, null, "testfile")); assertThrown!Exception(parseSDL(rec, `name "hello" { world }`, null, "testfile")); assertThrown!Exception(parseSDL(rec, `name "" versions "hello" 10` , null, "testfile")); } unittest { // test basic serialization PackageRecipe p; p.name = "test"; p.authors = ["foo", "bar"]; p.buildSettings.dflags["-windows"] = ["-a"]; p.buildSettings.lflags[""] = ["-b", "-c"]; auto sdl = toSDL(p).toSDLDocument(); assert(sdl == `name "test" authors "foo" "bar" dflags "-a" platform="windows" lflags "-b" "-c" `); } unittest { auto sdl = "name \"test\"\nsourcePaths"; PackageRecipe rec; parseSDL(rec, sdl, null, "testfile"); assert("" in rec.buildSettings.sourcePaths); } dub-1.19.0/source/dub/semver.d000066400000000000000000000307101360435400500160750ustar00rootroot00000000000000/** Implementes version validation and comparison according to the semantic versioning specification. The general format of a semantiv version is: a.b.c[-x.y...][+x.y...] a/b/c must be integer numbers with no leading zeros, and x/y/... must be either numbers or identifiers containing only ASCII alphabetic characters or hyphens. Identifiers may not start with a digit. See_Also: http://semver.org/ Copyright: © 2013-2016 rejectedsoftware e.K. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig */ module dub.semver; import std.range; import std.string; import std.algorithm : max; import std.conv; @safe: /** Validates a version string according to the SemVer specification. */ bool isValidVersion(string ver) pure @nogc { // NOTE: this is not by spec, but to ensure sane input if (ver.length > 256) return false; // a auto sepi = ver.indexOf('.'); if (sepi < 0) return false; if (!isValidNumber(ver[0 .. sepi])) return false; ver = ver[sepi+1 .. $]; // c sepi = ver.indexOf('.'); if (sepi < 0) return false; if (!isValidNumber(ver[0 .. sepi])) return false; ver = ver[sepi+1 .. $]; // c sepi = ver.indexOfAny("-+"); if (sepi < 0) sepi = ver.length; if (!isValidNumber(ver[0 .. sepi])) return false; ver = ver[sepi .. $]; // prerelease tail if (ver.length > 0 && ver[0] == '-') { ver = ver[1 .. $]; sepi = ver.indexOf('+'); if (sepi < 0) sepi = ver.length; if (!isValidIdentifierChain(ver[0 .. sepi])) return false; ver = ver[sepi .. $]; } // build tail if (ver.length > 0 && ver[0] == '+') { ver = ver[1 .. $]; if (!isValidIdentifierChain(ver, true)) return false; ver = null; } assert(ver.length == 0); return true; } /// unittest { assert(isValidVersion("1.9.0")); assert(isValidVersion("0.10.0")); assert(!isValidVersion("01.9.0")); assert(!isValidVersion("1.09.0")); assert(!isValidVersion("1.9.00")); assert(isValidVersion("1.0.0-alpha")); assert(isValidVersion("1.0.0-alpha.1")); assert(isValidVersion("1.0.0-0.3.7")); assert(isValidVersion("1.0.0-x.7.z.92")); assert(isValidVersion("1.0.0-x.7-z.92")); assert(!isValidVersion("1.0.0-00.3.7")); assert(!isValidVersion("1.0.0-0.03.7")); assert(isValidVersion("1.0.0-alpha+001")); assert(isValidVersion("1.0.0+20130313144700")); assert(isValidVersion("1.0.0-beta+exp.sha.5114f85")); assert(!isValidVersion(" 1.0.0")); assert(!isValidVersion("1. 0.0")); assert(!isValidVersion("1.0 .0")); assert(!isValidVersion("1.0.0 ")); assert(!isValidVersion("1.0.0-a_b")); assert(!isValidVersion("1.0.0+")); assert(!isValidVersion("1.0.0-")); assert(!isValidVersion("1.0.0-+a")); assert(!isValidVersion("1.0.0-a+")); assert(!isValidVersion("1.0")); assert(!isValidVersion("1.0-1.0")); } /** Determines if a given valid SemVer version has a pre-release suffix. */ bool isPreReleaseVersion(string ver) pure @nogc in { assert(isValidVersion(ver)); } body { foreach (i; 0 .. 2) { auto di = ver.indexOf('.'); assert(di > 0); ver = ver[di+1 .. $]; } auto di = ver.indexOf('-'); if (di < 0) return false; return isValidNumber(ver[0 .. di]); } /// unittest { assert(isPreReleaseVersion("1.0.0-alpha")); assert(isPreReleaseVersion("1.0.0-alpha+b1")); assert(isPreReleaseVersion("0.9.0-beta.1")); assert(!isPreReleaseVersion("0.9.0")); assert(!isPreReleaseVersion("0.9.0+b1")); } /** Compares the precedence of two SemVer version strings. The version strings must be validated using `isValidVersion` before being passed to this function. Note that the build meta data suffix (if any) is being ignored when comparing version numbers. Returns: Returns a negative number if `a` is a lower version than `b`, `0` if they are equal, and a positive number otherwise. */ int compareVersions(string a, string b) pure @nogc { // compare a.b.c numerically if (auto ret = compareNumber(a, b)) return ret; assert(a[0] == '.' && b[0] == '.'); a = a[1 .. $]; b = b[1 .. $]; if (auto ret = compareNumber(a, b)) return ret; assert(a[0] == '.' && b[0] == '.'); a = a[1 .. $]; b = b[1 .. $]; if (auto ret = compareNumber(a, b)) return ret; // give precedence to non-prerelease versions bool apre = a.length > 0 && a[0] == '-'; bool bpre = b.length > 0 && b[0] == '-'; if (apre != bpre) return bpre - apre; if (!apre) return 0; // compare the prerelease tail lexicographically do { a = a[1 .. $]; b = b[1 .. $]; if (auto ret = compareIdentifier(a, b)) return ret; } while (a.length > 0 && b.length > 0 && a[0] != '+' && b[0] != '+'); // give longer prerelease tails precedence bool aempty = a.length == 0 || a[0] == '+'; bool bempty = b.length == 0 || b[0] == '+'; if (aempty == bempty) { assert(aempty); return 0; } return bempty - aempty; } /// unittest { assert(compareVersions("1.0.0", "1.0.0") == 0); assert(compareVersions("1.0.0+b1", "1.0.0+b2") == 0); assert(compareVersions("1.0.0", "2.0.0") < 0); assert(compareVersions("1.0.0-beta", "1.0.0") < 0); assert(compareVersions("1.0.1", "1.0.0") > 0); } unittest { void assertLess(string a, string b) { assert(compareVersions(a, b) < 0, "Failed for "~a~" < "~b); assert(compareVersions(b, a) > 0); assert(compareVersions(a, a) == 0); assert(compareVersions(b, b) == 0); } assertLess("1.0.0", "2.0.0"); assertLess("2.0.0", "2.1.0"); assertLess("2.1.0", "2.1.1"); assertLess("1.0.0-alpha", "1.0.0"); assertLess("1.0.0-alpha", "1.0.0-alpha.1"); assertLess("1.0.0-alpha.1", "1.0.0-alpha.beta"); assertLess("1.0.0-alpha.beta", "1.0.0-beta"); assertLess("1.0.0-beta", "1.0.0-beta.2"); assertLess("1.0.0-beta.2", "1.0.0-beta.11"); assertLess("1.0.0-beta.11", "1.0.0-rc.1"); assertLess("1.0.0-rc.1", "1.0.0"); assert(compareVersions("1.0.0", "1.0.0+1.2.3") == 0); assert(compareVersions("1.0.0", "1.0.0+1.2.3-2") == 0); assert(compareVersions("1.0.0+asdasd", "1.0.0+1.2.3") == 0); assertLess("2.0.0", "10.0.0"); assertLess("1.0.0-2", "1.0.0-10"); assertLess("1.0.0-99", "1.0.0-1a"); assertLess("1.0.0-99", "1.0.0-a"); assertLess("1.0.0-alpha", "1.0.0-alphb"); assertLess("1.0.0-alphz", "1.0.0-alphz0"); assertLess("1.0.0-alphZ", "1.0.0-alpha"); } /** Increments a given (partial) version number to the next higher version. Prerelease and build metadata information is ignored. The given version can skip the minor and patch digits. If no digits are skipped, the next minor version will be selected. If the patch or minor versions are skipped, the next major version will be selected. This function corresponds to the semantivs of the "~>" comparison operator's upper bound. The semantics of this are the same as for the "approximate" version specifier from rubygems. (https://github.com/rubygems/rubygems/tree/81d806d818baeb5dcb6398ca631d772a003d078e/lib/rubygems/version.rb) See_Also: `expandVersion` */ string bumpVersion(string ver) pure { // Cut off metadata and prerelease information. auto mi = ver.indexOfAny("+-"); if (mi > 0) ver = ver[0..mi]; // Increment next to last version from a[.b[.c]]. auto splitted = () @trusted { return split(ver, "."); } (); // DMD 2.065.0 assert(splitted.length > 0 && splitted.length <= 3, "Version corrupt: " ~ ver); auto to_inc = splitted.length == 3? 1 : 0; splitted = splitted[0 .. to_inc+1]; splitted[to_inc] = to!string(to!int(splitted[to_inc]) + 1); // Fill up to three compontents to make valid SemVer version. while (splitted.length < 3) splitted ~= "0"; return splitted.join("."); } /// unittest { assert("1.0.0" == bumpVersion("0")); assert("1.0.0" == bumpVersion("0.0")); assert("0.1.0" == bumpVersion("0.0.0")); assert("1.3.0" == bumpVersion("1.2.3")); assert("1.3.0" == bumpVersion("1.2.3+metadata")); assert("1.3.0" == bumpVersion("1.2.3-pre.release")); assert("1.3.0" == bumpVersion("1.2.3-pre.release+metadata")); } /** Increments a given version number to the next incompatible version. Prerelease and build metadata information is removed. This implements the "^" comparison operator, which represents "nonbreaking semver compatibility." With 0.x.y releases, any release can break. With x.y.z releases, only major releases can break. */ string bumpIncompatibleVersion(string ver) pure { // Cut off metadata and prerelease information. auto mi = ver.indexOfAny("+-"); if (mi > 0) ver = ver[0..mi]; // Increment next to last version from a[.b[.c]]. auto splitted = () @trusted { return split(ver, "."); } (); // DMD 2.065.0 assert(splitted.length == 3, "Version corrupt: " ~ ver); if (splitted[0] == "0") splitted[2] = to!string(to!int(splitted[2]) + 1); else splitted = [to!string(to!int(splitted[0]) + 1), "0", "0"]; return splitted.join("."); } /// unittest { assert(bumpIncompatibleVersion("0.0.0") == "0.0.1"); assert(bumpIncompatibleVersion("0.1.2") == "0.1.3"); assert(bumpIncompatibleVersion("1.0.0") == "2.0.0"); assert(bumpIncompatibleVersion("1.2.3") == "2.0.0"); assert(bumpIncompatibleVersion("1.2.3+metadata") == "2.0.0"); assert(bumpIncompatibleVersion("1.2.3-pre.release") == "2.0.0"); assert(bumpIncompatibleVersion("1.2.3-pre.release+metadata") == "2.0.0"); } /** Takes a partial version and expands it to a valid SemVer version. This function corresponds to the semantivs of the "~>" comparison operator's lower bound. See_Also: `bumpVersion` */ string expandVersion(string ver) pure { auto mi = ver.indexOfAny("+-"); auto sub = ""; if (mi > 0) { sub = ver[mi..$]; ver = ver[0..mi]; } auto splitted = () @trusted { return split(ver, "."); } (); // DMD 2.065.0 assert(splitted.length > 0 && splitted.length <= 3, "Version corrupt: " ~ ver); while (splitted.length < 3) splitted ~= "0"; return splitted.join(".") ~ sub; } /// unittest { assert("1.0.0" == expandVersion("1")); assert("1.0.0" == expandVersion("1.0")); assert("1.0.0" == expandVersion("1.0.0")); // These are rather excotic variants... assert("1.0.0-pre.release" == expandVersion("1-pre.release")); assert("1.0.0+meta" == expandVersion("1+meta")); assert("1.0.0-pre.release+meta" == expandVersion("1-pre.release+meta")); } private int compareIdentifier(ref string a, ref string b) pure @nogc { bool anumber = true; bool bnumber = true; bool aempty = true, bempty = true; int res = 0; while (true) { if (a[0] != b[0] && res == 0) res = a[0] - b[0]; if (anumber && (a[0] < '0' || a[0] > '9')) anumber = false; if (bnumber && (b[0] < '0' || b[0] > '9')) bnumber = false; a = a[1 .. $]; b = b[1 .. $]; aempty = !a.length || a[0] == '.' || a[0] == '+'; bempty = !b.length || b[0] == '.' || b[0] == '+'; if (aempty || bempty) break; } if (anumber && bnumber) { // the !empty value might be an indentifier instead of a number, but identifiers always have precedence if (aempty != bempty) return bempty - aempty; return res; } else { if (anumber && aempty) return -1; if (bnumber && bempty) return 1; // this assumption is necessary to correctly classify 111A > 11111 (ident always > number)! static assert('0' < 'a' && '0' < 'A'); if (res != 0) return res; return bempty - aempty; } } private int compareNumber(ref string a, ref string b) pure @nogc { int res = 0; while (true) { if (a[0] != b[0] && res == 0) res = a[0] - b[0]; a = a[1 .. $]; b = b[1 .. $]; auto aempty = !a.length || (a[0] < '0' || a[0] > '9'); auto bempty = !b.length || (b[0] < '0' || b[0] > '9'); if (aempty != bempty) return bempty - aempty; if (aempty) return res; } } private bool isValidIdentifierChain(string str, bool allow_leading_zeros = false) pure @nogc { if (str.length == 0) return false; while (str.length) { auto end = str.indexOf('.'); if (end < 0) end = str.length; if (!isValidIdentifier(str[0 .. end], allow_leading_zeros)) return false; if (end < str.length) str = str[end+1 .. $]; else break; } return true; } private bool isValidIdentifier(string str, bool allow_leading_zeros = false) pure @nogc { if (str.length < 1) return false; bool numeric = true; foreach (ch; str) { switch (ch) { default: return false; case 'a': .. case 'z': case 'A': .. case 'Z': case '-': numeric = false; break; case '0': .. case '9': break; } } if (!allow_leading_zeros && numeric && str[0] == '0' && str.length > 1) return false; return true; } private bool isValidNumber(string str) pure @nogc { if (str.length < 1) return false; foreach (ch; str) if (ch < '0' || ch > '9') return false; // don't allow leading zeros if (str[0] == '0' && str.length > 1) return false; return true; } private ptrdiff_t indexOfAny(string str, in char[] chars) pure @nogc { ptrdiff_t ret = -1; foreach (ch; chars) { auto idx = str.indexOf(ch); if (idx >= 0 && (ret < 0 || idx < ret)) ret = idx; } return ret; } dub-1.19.0/source/dub/version_.d000066400000000000000000000000621360435400500164150ustar00rootroot00000000000000module dub.version_; enum dubVersion = "v1.19.0"; dub-1.19.0/test/000077500000000000000000000000001360435400500133335ustar00rootroot00000000000000dub-1.19.0/test/.gitignore000066400000000000000000000004741360435400500153300ustar00rootroot00000000000000*.a *.lib *.so *.dll 1-exec-simple/exec-simple 1-staticLib-simple/__test__library__ 2-dynLib-dep/dynlib-dep 2-sourceLib-dep/sourcelib-dep 2-staticLib-dep/staticlib-dep custom-unittest/custom-unittest path-subpackage-ref/test subpackage-ref/test subpackage-common-with-sourcefile-globbing/mypackage* /test_registry dub-1.19.0/test/0-init-fail-json.sh000077500000000000000000000007631360435400500166600ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh packname="0-init-fail-pack" deps="logger PACKAGE_DONT_EXIST" # would be very unlucky if it does exist... if $$DUB init -n $packname $deps -f json 2>/dev/null; then die $LINENO 'Init with unknown non-existing dependency expected to fail' fi function cleanup { rm -rf $packname } if [ -e $packname/dub.json ]; then # package is there, it should have failed cleanup die $LINENO "$packname/dub.json was not created" fi dub-1.19.0/test/0-init-fail.sh000077500000000000000000000007471360435400500157130ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh packname="0-init-fail-pack" deps="logger PACKAGE_DONT_EXIST" # would be very unlucky if it does exist... if $DUB init -n $packname $deps 2>/dev/null; then die $LINENO 'Init with unknown non-existing dependency expected to fail' fi function cleanup { rm -rf $packname } if [ -e $packname/dub.sdl ]; then # package is there, it should have failed cleanup die $LINENO "$packname/dub.sdl was not created" fi dub-1.19.0/test/0-init-interactive.dub.sdl000066400000000000000000000001171360435400500202220ustar00rootroot00000000000000name "test" description "desc" authors "author" copyright "copy" license "gpl" dub-1.19.0/test/0-init-interactive.sh000077500000000000000000000007521360435400500173110ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh packname="0-init-interactive" echo -e "sdl\ntest\ndesc\nauthor\ngpl\ncopy\n\n" | $DUB init $packname function cleanup { rm -rf $packname } if [ ! -e $packname/dub.sdl ]; then # it failed cleanup die $LINENO 'No dub.sdl file has been generated.' fi if ! diff $packname/dub.sdl "$CURR_DIR"/0-init-interactive.dub.sdl; then cleanup die $LINENO 'Contents of generated dub.sdl not as expected.' fi cleanup dub-1.19.0/test/0-init-multi-json.sh000077500000000000000000000012311360435400500170660ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh packname="0-init-multi-pack" deps="openssl logger" type="vibe.d" $DUB init -n $packname $deps --type=$type -f json function cleanup { rm -rf $packname } if [ ! -e $packname/dub.json ]; then die $LINENO '$packname/dub.json not created' else # check if resulting dub.json has all dependencies in tow deps="$deps vibe-d"; IFS=" " read -a arr <<< "$deps" for ele in "${arr[@]}" do if [ `grep -c "$ele" $packname/dub.json` -ne 1 ]; then #something went wrong cleanup die $LINENO "$ele not in $packname/dub.json" fi done cleanup fi dub-1.19.0/test/0-init-multi.sh000077500000000000000000000012531360435400500161230ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh packname="0-init-multi-pack" deps="openssl logger" type="vibe.d" $DUB init -n $packname $deps --type=$type --format sdl function cleanup { rm -rf $packname } if [ ! -e $packname/dub.sdl ]; then cleanup die $LINENO 'No dub.sdl file has been generated.' else # check if resulting dub.sdl has all dependencies in tow deps="$deps vibe-d"; IFS=" " read -a arr <<< "$deps" for ele in "${arr[@]}" do if [ `grep -c "$ele" $packname/dub.sdl` -ne 1 ]; then #something went wrong cleanup die $LINENO "$ele not in $packname/dub.sdl" fi done cleanup fi dub-1.19.0/test/0-init-simple-json.sh000077500000000000000000000004351360435400500172320ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh packname="0-init-simple-pack" $DUB init -n $packname -f json function cleanup { rm -rf $packname } if [ ! -e $packname/dub.json ]; then cleanup die $LINENO 'No dub.json file has been generated.' fi cleanup dub-1.19.0/test/0-init-simple.sh000077500000000000000000000004541360435400500162640ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh packname="0-init-simple-pack" $DUB init -n $packname --format sdl function cleanup { rm -rf $packname } if [ ! -e $packname/dub.sdl ]; then # it failed cleanup die $LINENO 'No dub.sdl file has been generated.' fi cleanup dub-1.19.0/test/1-dynLib-simple/000077500000000000000000000000001360435400500162015ustar00rootroot00000000000000dub-1.19.0/test/1-dynLib-simple/.no_build_gdc000066400000000000000000000000001360435400500206000ustar00rootroot00000000000000dub-1.19.0/test/1-dynLib-simple/.no_build_ldc2000066400000000000000000000000001360435400500206670ustar00rootroot00000000000000dub-1.19.0/test/1-dynLib-simple/.no_run000066400000000000000000000000001360435400500174700ustar00rootroot00000000000000dub-1.19.0/test/1-dynLib-simple/dub.json000066400000000000000000000001041360435400500176410ustar00rootroot00000000000000{ "name": "dynlib-simple", "targetType": "dynamicLibrary" } dub-1.19.0/test/1-dynLib-simple/source/000077500000000000000000000000001360435400500175015ustar00rootroot00000000000000dub-1.19.0/test/1-dynLib-simple/source/dynlib/000077500000000000000000000000001360435400500207625ustar00rootroot00000000000000dub-1.19.0/test/1-dynLib-simple/source/dynlib/app.d000066400000000000000000000001221360435400500217020ustar00rootroot00000000000000module dynlib.app; import std.stdio; void entry() { writeln(__FUNCTION__); } dub-1.19.0/test/1-exec-simple-package-json/000077500000000000000000000000001360435400500202445ustar00rootroot00000000000000dub-1.19.0/test/1-exec-simple-package-json/package.json000066400000000000000000000000761360435400500225350ustar00rootroot00000000000000{ "name": "exec-simple", "targetType": "executable" } dub-1.19.0/test/1-exec-simple-package-json/source/000077500000000000000000000000001360435400500215445ustar00rootroot00000000000000dub-1.19.0/test/1-exec-simple-package-json/source/app.d000066400000000000000000000000761360435400500224740ustar00rootroot00000000000000import std.stdio; void main() { writeln(__FUNCTION__); } dub-1.19.0/test/1-exec-simple/000077500000000000000000000000001360435400500157045ustar00rootroot00000000000000dub-1.19.0/test/1-exec-simple/dub.json000066400000000000000000000000761360435400500173540ustar00rootroot00000000000000{ "name": "exec-simple", "targetType": "executable" } dub-1.19.0/test/1-exec-simple/source/000077500000000000000000000000001360435400500172045ustar00rootroot00000000000000dub-1.19.0/test/1-exec-simple/source/app.d000066400000000000000000000000761360435400500201340ustar00rootroot00000000000000import std.stdio; void main() { writeln(__FUNCTION__); } dub-1.19.0/test/1-sourceLib-simple/000077500000000000000000000000001360435400500167075ustar00rootroot00000000000000dub-1.19.0/test/1-sourceLib-simple/.no_build000066400000000000000000000000001360435400500204710ustar00rootroot00000000000000dub-1.19.0/test/1-sourceLib-simple/dub.json000066400000000000000000000001061360435400500203510ustar00rootroot00000000000000{ "name": "sourcelib-simple", "targetType": "sourceLibrary" } dub-1.19.0/test/1-sourceLib-simple/source/000077500000000000000000000000001360435400500202075ustar00rootroot00000000000000dub-1.19.0/test/1-sourceLib-simple/source/sourcelib/000077500000000000000000000000001360435400500221765ustar00rootroot00000000000000dub-1.19.0/test/1-sourceLib-simple/source/sourcelib/app.d000066400000000000000000000001251360435400500231210ustar00rootroot00000000000000module sourcelib.app; import std.stdio; void entry() { writeln(__FUNCTION__); } dub-1.19.0/test/1-staticLib-simple/000077500000000000000000000000001360435400500166765ustar00rootroot00000000000000dub-1.19.0/test/1-staticLib-simple/.no_run000066400000000000000000000000001360435400500201650ustar00rootroot00000000000000dub-1.19.0/test/1-staticLib-simple/dub.json000066400000000000000000000001061360435400500203400ustar00rootroot00000000000000{ "name": "staticlib-simple", "targetType": "staticLibrary" } dub-1.19.0/test/1-staticLib-simple/source/000077500000000000000000000000001360435400500201765ustar00rootroot00000000000000dub-1.19.0/test/1-staticLib-simple/source/staticlib/000077500000000000000000000000001360435400500221545ustar00rootroot00000000000000dub-1.19.0/test/1-staticLib-simple/source/staticlib/app.d000066400000000000000000000001251360435400500230770ustar00rootroot00000000000000module staticlib.app; import std.stdio; void entry() { writeln(__FUNCTION__); } dub-1.19.0/test/2-dynLib-dep/000077500000000000000000000000001360435400500154615ustar00rootroot00000000000000dub-1.19.0/test/2-dynLib-dep/dub.json000066400000000000000000000001651360435400500171300ustar00rootroot00000000000000{ "name": "dynlib-dep", "dependencies": { "dynlib-simple": { "path": "../1-dynLib-simple/" } } } dub-1.19.0/test/2-dynLib-dep/source/000077500000000000000000000000001360435400500167615ustar00rootroot00000000000000dub-1.19.0/test/2-dynLib-dep/source/app.d000066400000000000000000000000751360435400500177100ustar00rootroot00000000000000module app; import dynlib.app; void main() { entry(); } dub-1.19.0/test/2-dynLib-with-staticLib-dep/000077500000000000000000000000001360435400500203465ustar00rootroot00000000000000dub-1.19.0/test/2-dynLib-with-staticLib-dep/.no_build_gdc000066400000000000000000000000001360435400500227450ustar00rootroot00000000000000dub-1.19.0/test/2-dynLib-with-staticLib-dep/.no_build_ldc2000066400000000000000000000000001360435400500230340ustar00rootroot00000000000000dub-1.19.0/test/2-dynLib-with-staticLib-dep/.no_run000066400000000000000000000000001360435400500216350ustar00rootroot00000000000000dub-1.19.0/test/2-dynLib-with-staticLib-dep/dub.json000066400000000000000000000002561360435400500220160ustar00rootroot00000000000000{ "name": "dynlib-with-staticlib-dep", "targetType": "dynamicLibrary", "dependencies": { "staticlib-simple": { "path": "../1-staticLib-simple/" } } } dub-1.19.0/test/2-dynLib-with-staticLib-dep/source/000077500000000000000000000000001360435400500216465ustar00rootroot00000000000000dub-1.19.0/test/2-dynLib-with-staticLib-dep/source/dynlib/000077500000000000000000000000001360435400500231275ustar00rootroot00000000000000dub-1.19.0/test/2-dynLib-with-staticLib-dep/source/dynlib/app.d000066400000000000000000000001301360435400500240460ustar00rootroot00000000000000module dynlib.app; import std.stdio; import staticlib.app; void foo() { entry(); } dub-1.19.0/test/2-sourceLib-dep/000077500000000000000000000000001360435400500161675ustar00rootroot00000000000000dub-1.19.0/test/2-sourceLib-dep/dub.json000066400000000000000000000002661360435400500176400ustar00rootroot00000000000000{ "name": "sourcelib-dep", "description": "Testing sourceLibrary dependency.", "dependencies": { "sourcelib-simple": { "path": "../1-sourceLib-simple/" } } } dub-1.19.0/test/2-sourceLib-dep/source/000077500000000000000000000000001360435400500174675ustar00rootroot00000000000000dub-1.19.0/test/2-sourceLib-dep/source/app.d000066400000000000000000000001001360435400500204030ustar00rootroot00000000000000module app; import sourcelib.app; void main() { entry(); } dub-1.19.0/test/2-staticLib-dep/000077500000000000000000000000001360435400500161565ustar00rootroot00000000000000dub-1.19.0/test/2-staticLib-dep/dub.json000066400000000000000000000002661360435400500176270ustar00rootroot00000000000000{ "name": "staticlib-dep", "description": "Testing staticLibrary dependency.", "dependencies": { "staticlib-simple": { "path": "../1-staticLib-simple/" } } } dub-1.19.0/test/2-staticLib-dep/source/000077500000000000000000000000001360435400500174565ustar00rootroot00000000000000dub-1.19.0/test/2-staticLib-dep/source/app.d000066400000000000000000000001001360435400500203720ustar00rootroot00000000000000module app; import staticlib.app; void main() { entry(); } dub-1.19.0/test/3-copyFiles/000077500000000000000000000000001360435400500154305ustar00rootroot00000000000000dub-1.19.0/test/3-copyFiles/data/000077500000000000000000000000001360435400500163415ustar00rootroot00000000000000dub-1.19.0/test/3-copyFiles/data/file_to_copy.txt000066400000000000000000000000311360435400500215470ustar00rootroot00000000000000file_to_copy.txt content dub-1.19.0/test/3-copyFiles/data/file_to_copy_mask1.txt000066400000000000000000000000361360435400500226500ustar00rootroot00000000000000file_to_copy_mask1.txt contentdub-1.19.0/test/3-copyFiles/data/file_to_copy_mask2.txt000066400000000000000000000000371360435400500226520ustar00rootroot00000000000000file_to_copy_mask2.txt content dub-1.19.0/test/3-copyFiles/data/res/000077500000000000000000000000001360435400500171325ustar00rootroot00000000000000dub-1.19.0/test/3-copyFiles/data/res/.nocopy/000077500000000000000000000000001360435400500205175ustar00rootroot00000000000000dub-1.19.0/test/3-copyFiles/data/res/.nocopy/file_inside_dot_prefixed_dir.txt000066400000000000000000000000151360435400500271200ustar00rootroot00000000000000some content dub-1.19.0/test/3-copyFiles/data/res/hdpi/000077500000000000000000000000001360435400500200565ustar00rootroot00000000000000dub-1.19.0/test/3-copyFiles/data/res/hdpi/file1.txt000066400000000000000000000000231360435400500216120ustar00rootroot00000000000000hdpi/file1 content dub-1.19.0/test/3-copyFiles/data/res/hdpi/file2.txt000066400000000000000000000000231360435400500216130ustar00rootroot00000000000000hdpi/file2 content dub-1.19.0/test/3-copyFiles/data/res/hdpi/file3.txt000066400000000000000000000000231360435400500216140ustar00rootroot00000000000000hdpi/file3 content dub-1.19.0/test/3-copyFiles/data/res/hdpi/nested_dir/000077500000000000000000000000001360435400500221765ustar00rootroot00000000000000dub-1.19.0/test/3-copyFiles/data/res/hdpi/nested_dir/nested_file.txt000066400000000000000000000000501360435400500252130ustar00rootroot00000000000000hdpi/nested_dir/nested_file.txt content dub-1.19.0/test/3-copyFiles/data/res/i18n/000077500000000000000000000000001360435400500177115ustar00rootroot00000000000000dub-1.19.0/test/3-copyFiles/data/res/i18n/resource_en.txt000066400000000000000000000000301360435400500227540ustar00rootroot00000000000000i18n - english resourcesdub-1.19.0/test/3-copyFiles/data/res/i18n/resource_fr.txt000066400000000000000000000000301360435400500227610ustar00rootroot00000000000000i18n - french resources dub-1.19.0/test/3-copyFiles/data/res/ldpi/000077500000000000000000000000001360435400500200625ustar00rootroot00000000000000dub-1.19.0/test/3-copyFiles/data/res/ldpi/file1.txt000066400000000000000000000000231360435400500216160ustar00rootroot00000000000000ldpi/file1 content dub-1.19.0/test/3-copyFiles/data/res/ldpi/file2.txt000066400000000000000000000000231360435400500216170ustar00rootroot00000000000000ldpi/file2 content dub-1.19.0/test/3-copyFiles/data/res/ldpi/file3.txt000066400000000000000000000000231360435400500216200ustar00rootroot00000000000000ldpi/file3 content dub-1.19.0/test/3-copyFiles/data/res/mdpi/000077500000000000000000000000001360435400500200635ustar00rootroot00000000000000dub-1.19.0/test/3-copyFiles/data/res/mdpi/file1.txt000066400000000000000000000000231360435400500216170ustar00rootroot00000000000000mdpi/file1 content dub-1.19.0/test/3-copyFiles/data/res/mdpi/file2.txt000066400000000000000000000000231360435400500216200ustar00rootroot00000000000000mdpi/file2 content dub-1.19.0/test/3-copyFiles/data/res/mdpi/file3.txt000066400000000000000000000000231360435400500216210ustar00rootroot00000000000000mdpi/file3 content dub-1.19.0/test/3-copyFiles/dub.json000066400000000000000000000003101360435400500170670ustar00rootroot00000000000000{ "name": "copyfiles-test", "targetType": "executable", "targetPath": "bin", "copyFiles": [ "data/res", "data/res/*dpi", "data/file_to_copy.txt", "data/file_to_copy_mask*.txt"] } dub-1.19.0/test/3-copyFiles/source/000077500000000000000000000000001360435400500167305ustar00rootroot00000000000000dub-1.19.0/test/3-copyFiles/source/app.d000066400000000000000000000021361360435400500176570ustar00rootroot00000000000000import std.algorithm, std.array, std.file, std.path; void main(string[] args) { immutable root = args[0].dirName; // get the bin dir immutable pfx = root.length + "/".length; auto files = dirEntries(root, SpanMode.breadth).map!(n => n[pfx .. $]).array.sort().release; assert(files == [ "copyfiles-test", "file_to_copy.txt", "file_to_copy_mask1.txt", "file_to_copy_mask2.txt", "hdpi", "hdpi/file1.txt", "hdpi/file2.txt", "hdpi/file3.txt", "hdpi/nested_dir", "hdpi/nested_dir/nested_file.txt", "ldpi", "ldpi/file1.txt", "ldpi/file2.txt", "ldpi/file3.txt", "mdpi", "mdpi/file1.txt", "mdpi/file2.txt", "mdpi/file3.txt", "res", "res/.nocopy", "res/.nocopy/file_inside_dot_prefixed_dir.txt", "res/hdpi", "res/hdpi/file1.txt", "res/hdpi/file2.txt", "res/hdpi/file3.txt", "res/hdpi/nested_dir", "res/hdpi/nested_dir/nested_file.txt", "res/i18n", "res/i18n/resource_en.txt", "res/i18n/resource_fr.txt", "res/ldpi", "res/ldpi/file1.txt", "res/ldpi/file2.txt", "res/ldpi/file3.txt", "res/mdpi", "res/mdpi/file1.txt", "res/mdpi/file2.txt", "res/mdpi/file3.txt" ], files.join(", ") ); } dub-1.19.0/test/4-describe-data-1-list.sh000077500000000000000000000122361360435400500176350ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd "$CURR_DIR"/describe-project temp_file=$(mktemp $(basename $0).XXXXXX) function cleanup { rm $temp_file } trap cleanup EXIT if ! $DUB describe --compiler=$DC --filter-versions \ --data-list \ '--data= target-type , target-path , target-name ' \ '--data= working-directory ' \ --data=main-source-file \ '--data=dflags,lflags' \ '--data=libs, linker-files' \ '--data=source-files, copy-files' \ '--data=versions, debug-versions' \ --data=import-paths \ --data=string-import-paths \ --data=import-files \ --data=string-import-files \ --data=pre-generate-commands \ --data=post-generate-commands \ --data=pre-build-commands \ --data=post-build-commands \ '--data=requirements, options' \ > "$temp_file"; then die $LINENO 'Printing project data failed!' fi # Create the expected output path file to compare against. expected_file="$CURR_DIR/expected-describe-data-1-list-output" # --data=target-type echo "executable" > "$expected_file" echo >> "$expected_file" # --data=target-path echo "$CURR_DIR/describe-project/" >> "$expected_file" echo >> "$expected_file" # --data=target-name echo "describe-project" >> "$expected_file" echo >> "$expected_file" # --data=working-directory echo "$CURR_DIR/describe-project/" >> "$expected_file" echo >> "$expected_file" # --data=main-source-file echo "$CURR_DIR/describe-project/src/dummy.d" >> "$expected_file" echo >> "$expected_file" # --data=dflags echo "--some-dflag" >> "$expected_file" echo "--another-dflag" >> "$expected_file" echo >> "$expected_file" # --data=lflags echo "--some-lflag" >> "$expected_file" echo "--another-lflag" >> "$expected_file" echo >> "$expected_file" # --data=libs echo "somelib" >> "$expected_file" echo "anotherlib" >> "$expected_file" echo >> "$expected_file" # --data=linker-files echo "$CURR_DIR/describe-dependency-3/libdescribe-dependency-3.a" >> "$expected_file" echo "$CURR_DIR/describe-project/some.a" >> "$expected_file" echo "$CURR_DIR/describe-dependency-1/dep.a" >> "$expected_file" echo >> "$expected_file" # --data=source-files echo "$CURR_DIR/describe-project/src/dummy.d" >> "$expected_file" echo "$CURR_DIR/describe-dependency-1/source/dummy.d" >> "$expected_file" echo >> "$expected_file" # --data=copy-files echo "$CURR_DIR/describe-project/data/dummy.dat" >> "$expected_file" echo "$CURR_DIR/describe-dependency-1/data/*" >> "$expected_file" echo >> "$expected_file" # --data=versions echo "someVerIdent" >> "$expected_file" echo "anotherVerIdent" >> "$expected_file" echo "Have_describe_dependency_3" >> "$expected_file" echo >> "$expected_file" # --data=debug-versions echo "someDebugVerIdent" >> "$expected_file" echo "anotherDebugVerIdent" >> "$expected_file" echo >> "$expected_file" # --data=import-paths echo "$CURR_DIR/describe-project/src/" >> "$expected_file" echo "$CURR_DIR/describe-dependency-1/source/" >> "$expected_file" echo "$CURR_DIR/describe-dependency-2/some-path/" >> "$expected_file" echo "$CURR_DIR/describe-dependency-3/dep3-source/" >> "$expected_file" echo >> "$expected_file" # --data=string-import-paths echo "$CURR_DIR/describe-project/views/" >> "$expected_file" echo "$CURR_DIR/describe-dependency-2/some-extra-string-import-path/" >> "$expected_file" echo "$CURR_DIR/describe-dependency-3/dep3-string-import-path/" >> "$expected_file" echo >> "$expected_file" # --data=import-files echo "$CURR_DIR/describe-dependency-2/some-path/dummy.d" >> "$expected_file" echo >> "$expected_file" # --data=string-import-files echo "$CURR_DIR/describe-project/views/dummy.d" >> "$expected_file" #echo "$CURR_DIR/describe-dependency-2/some-extra-string-import-path/dummy.d" >> "$expected_file" # This is missing from result, is that a bug? echo >> "$expected_file" # --data=pre-generate-commands echo "./do-preGenerateCommands.sh" >> "$expected_file" echo "../describe-dependency-1/dependency-preGenerateCommands.sh" >> "$expected_file" echo >> "$expected_file" # --data=post-generate-commands echo "./do-postGenerateCommands.sh" >> "$expected_file" echo "../describe-dependency-1/dependency-postGenerateCommands.sh" >> "$expected_file" echo >> "$expected_file" # --data=pre-build-commands echo "./do-preBuildCommands.sh" >> "$expected_file" echo "../describe-dependency-1/dependency-preBuildCommands.sh" >> "$expected_file" echo >> "$expected_file" # --data=post-build-commands echo "./do-postBuildCommands.sh" >> "$expected_file" echo "../describe-dependency-1/dependency-postBuildCommands.sh" >> "$expected_file" echo >> "$expected_file" # --data=requirements echo "allowWarnings" >> "$expected_file" echo "disallowInlining" >> "$expected_file" #echo "requireContracts" >> "$expected_file" # Not sure if this (from a sourceLib dependency) should be missing from the result echo >> "$expected_file" # --data=options echo "debugMode" >> "$expected_file" echo "releaseMode" >> "$expected_file" echo "debugInfo" >> "$expected_file" echo "warnings" >> "$expected_file" #echo "stackStomping" >> "$expected_file" # Not sure if this (from a sourceLib dependency) should be missing from the result if ! diff "$expected_file" "$temp_file"; then die $LINENO 'The project data did not match the expected output!' fi dub-1.19.0/test/4-describe-data-2-dmd.sh000077500000000000000000000061051360435400500174250ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh if [ "${DC}" != "dmd" ]; then echo Skipping DMD-centric test on configuration that lacks DMD. exit fi cd "$CURR_DIR"/describe-project temp_file=$(mktemp $(basename $0).XXXXXX) function cleanup { rm $temp_file } trap cleanup EXIT if ! $DUB describe --compiler=$DC --filter-versions \ --data=main-source-file \ --data=dflags,lflags \ --data=libs,linker-files \ --data=source-files \ --data=versions \ --data=debug-versions \ --data=import-paths \ --data=string-import-paths \ --data=import-files \ --data=options \ > "$temp_file"; then die 'Printing project data failed!' fi # Create the expected output path file to compare against. expected_file="$CURR_DIR/expected-describe-data-2-dmd-output" # --data=main-source-file echo -n "'$CURR_DIR/describe-project/src/dummy.d' " > "$expected_file" # --data=dflags echo -n "--some-dflag " >> "$expected_file" echo -n "--another-dflag " >> "$expected_file" # --data=lflags echo -n "-L--some-lflag " >> "$expected_file" echo -n "-L--another-lflag " >> "$expected_file" # --data=libs echo -n "-L-lsomelib " >> "$expected_file" echo -n "-L-lanotherlib " >> "$expected_file" # --data=linker-files echo -n "'$CURR_DIR/describe-dependency-3/libdescribe-dependency-3.a' " >> "$expected_file" echo -n "'$CURR_DIR/describe-project/some.a' " >> "$expected_file" echo -n "'$CURR_DIR/describe-dependency-1/dep.a' " >> "$expected_file" # --data=source-files echo -n "'$CURR_DIR/describe-project/src/dummy.d' " >> "$expected_file" echo -n "'$CURR_DIR/describe-dependency-1/source/dummy.d' " >> "$expected_file" # --data=versions echo -n "-version=someVerIdent " >> "$expected_file" echo -n "-version=anotherVerIdent " >> "$expected_file" echo -n "-version=Have_describe_dependency_3 " >> "$expected_file" # --data=debug-versions echo -n "-debug=someDebugVerIdent " >> "$expected_file" echo -n "-debug=anotherDebugVerIdent " >> "$expected_file" # --data=import-paths echo -n "'-I$CURR_DIR/describe-project/src/' " >> "$expected_file" echo -n "'-I$CURR_DIR/describe-dependency-1/source/' " >> "$expected_file" echo -n "'-I$CURR_DIR/describe-dependency-2/some-path/' " >> "$expected_file" echo -n "'-I$CURR_DIR/describe-dependency-3/dep3-source/' " >> "$expected_file" # --data=string-import-paths echo -n "'-J$CURR_DIR/describe-project/views/' " >> "$expected_file" echo -n "'-J$CURR_DIR/describe-dependency-2/some-extra-string-import-path/' " >> "$expected_file" echo -n "'-J$CURR_DIR/describe-dependency-3/dep3-string-import-path/' " >> "$expected_file" # --data=import-files echo -n "'$CURR_DIR/describe-dependency-2/some-path/dummy.d' " >> "$expected_file" # --data=options echo -n "-debug " >> "$expected_file" echo -n "-release " >> "$expected_file" echo -n "-g " >> "$expected_file" echo -n "-wi" >> "$expected_file" #echo -n "-gx " >> "$expected_file" # Not sure if this (from a sourceLib dependency) should be missing from the result echo "" >> "$expected_file" if ! diff "$expected_file" "$temp_file"; then die 'The project data did not match the expected output!' fi dub-1.19.0/test/4-describe-data-3-zero-delim.sh000077500000000000000000000072441360435400500207360ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd "$CURR_DIR"/describe-project temp_file_normal=$(mktemp $(basename $0).XXXXXX) temp_file_zero_delim=$(mktemp $(basename $0).XXXXXX) function cleanup { rm $temp_file_normal rm $temp_file_zero_delim } trap cleanup EXIT # Test list-style project data if ! $DUB describe --compiler=$DC --data-list \ --data=target-type \ --data=target-path \ --data=target-name \ --data=working-directory \ --data=main-source-file \ --data=dflags \ --data=lflags \ --data=libs \ --data=linker-files \ --data=source-files \ --data=copy-files \ --data=versions \ --data=debug-versions \ --data=import-paths \ --data=string-import-paths \ --data=import-files \ --data=string-import-files \ --data=pre-generate-commands \ --data=post-generate-commands \ --data=pre-build-commands \ --data=post-build-commands \ --data=requirements \ --data=options \ > "$temp_file_normal"; then die 'Printing list-style project data failed!' fi if ! $DUB describe --compiler=$DC --data-0 --data-list \ --data=target-type \ --data=target-path \ --data=target-name \ --data=working-directory \ --data=main-source-file \ --data=dflags \ --data=lflags \ --data=libs \ --data=linker-files \ --data=source-files \ --data=copy-files \ --data=versions \ --data=debug-versions \ --data=import-paths \ --data=string-import-paths \ --data=import-files \ --data=string-import-files \ --data=pre-generate-commands \ --data=post-generate-commands \ --data=pre-build-commands \ --data=post-build-commands \ --data=requirements \ --data=options \ | xargs -0 printf "%s\n" > "$temp_file_zero_delim"; then die 'Printing null-delimited list-style project data failed!' fi if ! diff -Z "$temp_file_normal" "$temp_file_zero_delim"; then die 'The null-delimited list-style project data did not match the expected output!' fi # Test --import-paths if ! $DUB describe --compiler=$DC --import-paths \ > "$temp_file_normal"; then die 'Printing --import-paths failed!' fi if ! $DUB describe --compiler=$DC --data-0 --import-paths \ | xargs -0 printf "%s\n" > "$temp_file_zero_delim"; then die 'Printing null-delimited --import-paths failed!' fi if ! diff -Z -B "$temp_file_normal" "$temp_file_zero_delim"; then die 'The null-delimited --import-paths data did not match the expected output!' fi # DMD-only beyond this point if [ "${DC}" != "dmd" ]; then echo Skipping DMD-centric tests on configuration that lacks DMD. exit fi # Test dmd-style --data=versions if ! $DUB describe --compiler=$DC --data=versions \ > "$temp_file_normal"; then die 'Printing dmd-style --data=versions failed!' fi if ! $DUB describe --compiler=$DC --data-0 --data=versions \ | xargs -0 printf "%s " > "$temp_file_zero_delim"; then die 'Printing null-delimited dmd-style --data=versions failed!' fi if ! diff -Z "$temp_file_normal" "$temp_file_zero_delim"; then die 'The null-delimited dmd-style --data=versions did not match the expected output!' fi # Test dmd-style --data=source-files if ! $DUB describe --compiler=$DC --data=source-files \ > "$temp_file_normal"; then die 'Printing dmd-style --data=source-files failed!' fi if ! $DUB describe --compiler=$DC --data-0 --data=source-files \ | xargs -0 printf "'%s' " > "$temp_file_zero_delim"; then die 'Printing null-delimited dmd-style --data=source-files failed!' fi if ! diff -Z "$temp_file_normal" "$temp_file_zero_delim"; then die 'The null-delimited dmd-style --data=source-files did not match the expected output!' fi dub-1.19.0/test/4-describe-import-paths.sh000077500000000000000000000015441360435400500202440ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd "$CURR_DIR"/describe-project temp_file=$(mktemp $(basename $0).XXXXXX) function cleanup { rm $temp_file } trap cleanup EXIT if ! $DUB describe --compiler=$DC --import-paths > "$temp_file"; then die 'Printing import paths failed!' fi # Create the expected output path file to compare against. echo "$CURR_DIR/describe-project/src/" > "$CURR_DIR/expected-import-path-output" echo "$CURR_DIR/describe-dependency-1/source/" >> "$CURR_DIR/expected-import-path-output" echo "$CURR_DIR/describe-dependency-2/some-path/" >> "$CURR_DIR/expected-import-path-output" echo "$CURR_DIR/describe-dependency-3/dep3-source/" >> "$CURR_DIR/expected-import-path-output" if ! diff "$CURR_DIR"/expected-import-path-output "$temp_file"; then die 'The import paths did not match the expected output!' fi dub-1.19.0/test/4-describe-json.sh000077500000000000000000000004541360435400500165650ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd "$CURR_DIR"/describe-project temp_file=$(mktemp $(basename $0).XXXXXX) function cleanup { rm $temp_file } trap cleanup EXIT if ! $DUB describe --compiler=$DC > "$temp_file"; then die 'Printing describe JSON failed!' fi dub-1.19.0/test/4-describe-string-import-paths.sh000077500000000000000000000015351360435400500215500ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd "$CURR_DIR"/describe-project temp_file=$(mktemp $(basename $0).XXXXXX) function cleanup { rm $temp_file } trap cleanup EXIT if ! $DUB describe --compiler=$DC --string-import-paths > "$temp_file"; then die 'Printing string import paths failed!' fi # Create the expected output path file to compare against. echo "$CURR_DIR/describe-project/views/" > "$CURR_DIR/expected-string-import-path-output" echo "$CURR_DIR/describe-dependency-2/some-extra-string-import-path/" >> "$CURR_DIR/expected-string-import-path-output" echo "$CURR_DIR/describe-dependency-3/dep3-string-import-path/" >> "$CURR_DIR/expected-string-import-path-output" if ! diff "$CURR_DIR"/expected-string-import-path-output "$temp_file"; then die 'The string import paths did not match the expected output!' fi dub-1.19.0/test/5-convert-stdout.sh000077500000000000000000000006401360435400500170340ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/1-exec-simple EXPECTED="name \"exec-simple\" targetType \"executable\"" RESULT=`${DUB} convert -s -f sdl` if [ ! -f dub.json ]; then die $LINENO 'Package recipe got modified!' fi if [ -f dub.sdl ]; then die $LINENO 'An SDL recipe got written.' fi if [ "$RESULT" != "$EXPECTED" ]; then die $LINENO 'Unexpected SDLang output.' fi dub-1.19.0/test/5-convert.sh000077500000000000000000000012611360435400500155140ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd "$CURR_DIR"/5-convert temp_file=$(mktemp $(basename $0).XXXXXX) function cleanup { rm $temp_file } trap cleanup EXIT cp dub.sdl dub.sdl.ref $DUB convert -f json if [ -f "dub.sdl" ]; then die $LINENO 'Old recipe file not removed.'; fi if [ ! -f "dub.json" ]; then die $LINENO 'New recipe file not created.'; fi $DUB convert -f sdl if [ -f "dub.json" ]; then die $LINENO 'Old recipe file not removed.'; fi if [ ! -f "dub.sdl" ]; then die $LINENO 'New recipe file not created.'; fi if ! diff "dub.sdl" "dub.sdl.ref"; then die $LINENO 'The project data did not match the expected output!' fi rm dub.sdl.ref dub-1.19.0/test/5-convert/000077500000000000000000000000001360435400500151555ustar00rootroot00000000000000dub-1.19.0/test/5-convert/.no_build000066400000000000000000000000021360435400500167410ustar00rootroot00000000000000 dub-1.19.0/test/5-convert/dub.sdl000066400000000000000000000022461360435400500164370ustar00rootroot00000000000000name "describe-dependency-1" version "~master" description "A test describe project" homepage "fake.com" authors "nobody" copyright "Copyright © 2015, nobody" license "BSD 2-clause" x:ddoxFilterArgs "dfa1" "dfa2" x:ddoxTool "ddoxtool" dependency "describe-dependency-1:sub1" version=">=0.0.0" targetType "sourceLibrary" subConfiguration "describe-dependency-1:sub1" "library" dflags "--another-dflag" lflags "--another-lflag" libs "anotherlib" sourceFiles "dep.lib" platform="windows" sourcePaths "source/" copyFiles "data/*" versions "anotherVerIdent" debugVersions "anotherDebugVerIdent" importPaths "source/" preGenerateCommands "../describe-dependency-1/dependency-preGenerateCommands.sh" platform="posix" postGenerateCommands "../describe-dependency-1/dependency-postGenerateCommands.sh" platform="posix" preBuildCommands "../describe-dependency-1/dependency-preBuildCommands.sh" platform="posix" postBuildCommands "../describe-dependency-1/dependency-postBuildCommands.sh" platform="posix" buildRequirements "requireContracts" buildOptions "stackStomping" configuration "my-dependency-1-config" { targetType "sourceLibrary" } subPackage { name "sub1" } subPackage { name "sub2" } dub-1.19.0/test/common.sh000066400000000000000000000010031360435400500151510ustar00rootroot00000000000000SOURCE_FILE=$_ set -ueEo pipefail function log() { echo -e "\033[0;33m[INFO] $@\033[0m" echo "[INFO] $@" >> $(dirname "${BASH_SOURCE[0]}")/test.log } # lineno[, msg] function die() { local line=$1 local msg=${2:-command failed} local supplemental=${3:-} echo "[ERROR] $SOURCE_FILE:$1 $msg" | tee -a $(dirname "${BASH_SOURCE[0]}")/test.log | cat 1>&2 if [ ! -z "$supplemental" ]; then echo "$supplemental" | >&2 sed 's|^| |g' fi exit 1 } trap 'die $LINENO' ERR dub-1.19.0/test/custom-source-main-bug487/000077500000000000000000000000001360435400500201035ustar00rootroot00000000000000dub-1.19.0/test/custom-source-main-bug487/.gitignore000066400000000000000000000000461360435400500220730ustar00rootroot00000000000000.dub docs.json __dummy.html *.o *.obj dub-1.19.0/test/custom-source-main-bug487/.no_run000066400000000000000000000000001360435400500213720ustar00rootroot00000000000000dub-1.19.0/test/custom-source-main-bug487/.no_test000066400000000000000000000000001360435400500215450ustar00rootroot00000000000000dub-1.19.0/test/custom-source-main-bug487/dub.json000066400000000000000000000001331360435400500215450ustar00rootroot00000000000000{ "name": "custom-source-main-bug487", "sourcePaths": ["mysrc"], "dependencies": { } } dub-1.19.0/test/custom-source-main-bug487/mysrc/000077500000000000000000000000001360435400500212405ustar00rootroot00000000000000dub-1.19.0/test/custom-source-main-bug487/mysrc/app.d000066400000000000000000000000201360435400500221550ustar00rootroot00000000000000void main() { } dub-1.19.0/test/custom-unittest/000077500000000000000000000000001360435400500165225ustar00rootroot00000000000000dub-1.19.0/test/custom-unittest/dub.json000066400000000000000000000006021360435400500201650ustar00rootroot00000000000000{ "name": "custom-unittest", "configurations": [ { "name": "application", "targetType": "executable" }, { "name": "library", "excludedSourceFiles": ["source/app.d"], "targetType": "library" }, { "name": "unittest", "targetType": "executable", "excludedSourceFiles": ["source/app.d"], "sourcePaths": ["test/"], "importPaths": ["test/"] } ] } dub-1.19.0/test/custom-unittest/source/000077500000000000000000000000001360435400500200225ustar00rootroot00000000000000dub-1.19.0/test/custom-unittest/source/app.d000066400000000000000000000001511360435400500207440ustar00rootroot00000000000000module app; import lib; import std.stdio; void main() { writeln("Running application."); libFunc(); } dub-1.19.0/test/custom-unittest/source/lib.d000066400000000000000000000001321360435400500207310ustar00rootroot00000000000000module lib; void libFunc() { import std.stdio; writefln("Library function called."); } dub-1.19.0/test/custom-unittest/test/000077500000000000000000000000001360435400500175015ustar00rootroot00000000000000dub-1.19.0/test/custom-unittest/test/main.d000066400000000000000000000001231360435400500205660ustar00rootroot00000000000000module main; void main() { import std.stdio; writefln("Running unit tests."); } dub-1.19.0/test/ddox.sh000077500000000000000000000011331360435400500146260ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh # gdc 4.8.5 not working with ddox due to missing # std.experimental.allocator.mallocator for libdparse if [ ${DC} = gdc ]; then exit 0 fi (cd $CURR_DIR/ddox/default && $DUB build -b ddox) grep -qF ddox_project $CURR_DIR/ddox/default/docs/index.html $DUB add-local $CURR_DIR/ddox/custom-tool (cd $CURR_DIR/ddox/custom && $DUB build -b ddox) grep -qF custom-tool $CURR_DIR/ddox/custom/docs/custom_tool_output diff $CURR_DIR/ddox/custom-tool/public/copied $CURR_DIR/ddox/custom/docs/copied $DUB remove-local $CURR_DIR/ddox/custom-tool dub-1.19.0/test/ddox.sh.min_frontend000066400000000000000000000000061360435400500173020ustar00rootroot000000000000002.072 dub-1.19.0/test/ddox/000077500000000000000000000000001360435400500142715ustar00rootroot00000000000000dub-1.19.0/test/ddox/.no_build000066400000000000000000000000001360435400500160530ustar00rootroot00000000000000dub-1.19.0/test/ddox/custom-tool/000077500000000000000000000000001360435400500165565ustar00rootroot00000000000000dub-1.19.0/test/ddox/custom-tool/.gitignore000066400000000000000000000000621360435400500205440ustar00rootroot00000000000000.dub docs.json __dummy.html *.o *.obj custom-tool dub-1.19.0/test/ddox/custom-tool/dub.sdl000066400000000000000000000001551360435400500200350ustar00rootroot00000000000000name "custom-tool" description "A minimal D application." copyright "Copyright © 2015, dawg" authors "dawg" dub-1.19.0/test/ddox/custom-tool/public/000077500000000000000000000000001360435400500200345ustar00rootroot00000000000000dub-1.19.0/test/ddox/custom-tool/public/copied000066400000000000000000000000101360435400500212110ustar00rootroot00000000000000content dub-1.19.0/test/ddox/custom-tool/source/000077500000000000000000000000001360435400500200565ustar00rootroot00000000000000dub-1.19.0/test/ddox/custom-tool/source/app.d000066400000000000000000000003201360435400500207760ustar00rootroot00000000000000import std.file, std.stdio, std.string; void main(string[] args) { if (args[1] != "generate-html") return; mkdirRecurse(args[$-1]); File(args[$-1]~"/custom_tool_output", "w").writeln(args.join(" ")); } dub-1.19.0/test/ddox/custom/000077500000000000000000000000001360435400500156035ustar00rootroot00000000000000dub-1.19.0/test/ddox/custom/.gitignore000066400000000000000000000000531360435400500175710ustar00rootroot00000000000000.dub docs docs.json __dummy.html *.o *.obj dub-1.19.0/test/ddox/custom/dub.sdl000066400000000000000000000000551360435400500170610ustar00rootroot00000000000000name "ddox-project" x:ddoxTool "custom-tool" dub-1.19.0/test/ddox/custom/source/000077500000000000000000000000001360435400500171035ustar00rootroot00000000000000dub-1.19.0/test/ddox/custom/source/ddox_project.d000066400000000000000000000000611360435400500217310ustar00rootroot00000000000000/// module ddox_project; /// docstring int foo; dub-1.19.0/test/ddox/default/000077500000000000000000000000001360435400500157155ustar00rootroot00000000000000dub-1.19.0/test/ddox/default/.gitignore000066400000000000000000000000531360435400500177030ustar00rootroot00000000000000.dub docs docs.json __dummy.html *.o *.obj dub-1.19.0/test/ddox/default/dub.sdl000066400000000000000000000000241360435400500171670ustar00rootroot00000000000000name "ddox-project" dub-1.19.0/test/ddox/default/source/000077500000000000000000000000001360435400500172155ustar00rootroot00000000000000dub-1.19.0/test/ddox/default/source/ddox_project.d000066400000000000000000000000611360435400500220430ustar00rootroot00000000000000/// module ddox_project; /// docstring int foo; dub-1.19.0/test/describe-dependency-1/000077500000000000000000000000001360435400500173655ustar00rootroot00000000000000dub-1.19.0/test/describe-dependency-1/.no_build000066400000000000000000000000021360435400500211510ustar00rootroot00000000000000 dub-1.19.0/test/describe-dependency-1/data/000077500000000000000000000000001360435400500202765ustar00rootroot00000000000000dub-1.19.0/test/describe-dependency-1/data/dummy-dep1.dat000066400000000000000000000000021360435400500227420ustar00rootroot00000000000000 dub-1.19.0/test/describe-dependency-1/dependency-postGenerateCommands.sh000077500000000000000000000000241360435400500261560ustar00rootroot00000000000000#!/usr/bin/env bash dub-1.19.0/test/describe-dependency-1/dependency-preGenerateCommands.sh000077500000000000000000000000241360435400500257570ustar00rootroot00000000000000#!/usr/bin/env bash dub-1.19.0/test/describe-dependency-1/dub.json000066400000000000000000000021171360435400500210330ustar00rootroot00000000000000{ "name": "describe-dependency-1", "targetType": "sourceLibrary", "description": "A test describe project", "authors": ["nobody"], "homepage": "fake.com", "license": "BSD 2-clause", "copyright": "Copyright © 2015, nobody", "sourceFiles-posix": ["dep.a"], "sourceFiles-windows": ["dep.lib"], "dflags": ["--another-dflag"], "lflags": ["--another-lflag"], "libs": ["anotherlib"], "copyFiles": ["data/*"], "versions": ["anotherVerIdent"], "debugVersions": ["anotherDebugVerIdent"], "preGenerateCommands-posix": ["../describe-dependency-1/dependency-preGenerateCommands.sh"], "postGenerateCommands-posix": ["../describe-dependency-1/dependency-postGenerateCommands.sh"], "preBuildCommands-posix": ["../describe-dependency-1/dependency-preBuildCommands.sh"], "postBuildCommands-posix": ["../describe-dependency-1/dependency-postBuildCommands.sh"], "buildRequirements": ["requireContracts"], "buildOptions": ["stackStomping"], "configurations": [ { "name": "my-dependency-1-config" } ], } dub-1.19.0/test/describe-dependency-1/otherdir/000077500000000000000000000000001360435400500212055ustar00rootroot00000000000000dub-1.19.0/test/describe-dependency-1/otherdir/dummy.d000066400000000000000000000000011360435400500224740ustar00rootroot00000000000000 dub-1.19.0/test/describe-dependency-1/source/000077500000000000000000000000001360435400500206655ustar00rootroot00000000000000dub-1.19.0/test/describe-dependency-1/source/dummy.d000066400000000000000000000000751360435400500221670ustar00rootroot00000000000000version (anotherVerIdent) {} debug (anotherDebugVerIdent) {} dub-1.19.0/test/describe-dependency-2/000077500000000000000000000000001360435400500173665ustar00rootroot00000000000000dub-1.19.0/test/describe-dependency-2/.no_build000066400000000000000000000000021360435400500211520ustar00rootroot00000000000000 dub-1.19.0/test/describe-dependency-2/dub.json000066400000000000000000000005341360435400500210350ustar00rootroot00000000000000{ "name": "describe-dependency-2", "targetType": "sourceLibrary", "description": "A test describe project", "authors": ["nobody"], "homepage": "fake.com", "license": "BSD 2-clause", "copyright": "Copyright © 2015, nobody", "importPaths": ["some-path"], "stringImportPaths": ["some-extra-string-import-path"], } dub-1.19.0/test/describe-dependency-2/some-extra-string-import-path/000077500000000000000000000000001360435400500252205ustar00rootroot00000000000000dub-1.19.0/test/describe-dependency-2/some-extra-string-import-path/dummy.d000066400000000000000000000000011360435400500265070ustar00rootroot00000000000000 dub-1.19.0/test/describe-dependency-2/some-path/000077500000000000000000000000001360435400500212635ustar00rootroot00000000000000dub-1.19.0/test/describe-dependency-2/some-path/dummy.d000066400000000000000000000000011360435400500225520ustar00rootroot00000000000000 dub-1.19.0/test/describe-dependency-3/000077500000000000000000000000001360435400500173675ustar00rootroot00000000000000dub-1.19.0/test/describe-dependency-3/.no_build000066400000000000000000000000021360435400500211530ustar00rootroot00000000000000 dub-1.19.0/test/describe-dependency-3/dep3-source/000077500000000000000000000000001360435400500215205ustar00rootroot00000000000000dub-1.19.0/test/describe-dependency-3/dep3-source/dummy.d000066400000000000000000000000011360435400500230070ustar00rootroot00000000000000 dub-1.19.0/test/describe-dependency-3/dep3-string-import-path/000077500000000000000000000000001360435400500237705ustar00rootroot00000000000000dub-1.19.0/test/describe-dependency-3/dep3-string-import-path/dummy.d000066400000000000000000000000011360435400500252570ustar00rootroot00000000000000 dub-1.19.0/test/describe-dependency-3/dub.json000066400000000000000000000006341360435400500210370ustar00rootroot00000000000000{ "name": "describe-dependency-3", "targetType": "staticLibrary", "description": "A test describe project", "authors": ["nobody"], "homepage": "fake.com", "license": "BSD 2-clause", "copyright": "Copyright © 2015, nobody", "importPaths": ["dep3-source"], "sourcePaths": ["dep3-source"], "stringImportPaths": ["dep3-string-import-path"], "buildOptions": ["profile"] } dub-1.19.0/test/describe-project/000077500000000000000000000000001360435400500165575ustar00rootroot00000000000000dub-1.19.0/test/describe-project/.no_build000066400000000000000000000000021360435400500203430ustar00rootroot00000000000000 dub-1.19.0/test/describe-project/data/000077500000000000000000000000001360435400500174705ustar00rootroot00000000000000dub-1.19.0/test/describe-project/data/dummy.dat000066400000000000000000000000021360435400500213050ustar00rootroot00000000000000 dub-1.19.0/test/describe-project/do-postGenerateCommands.sh000077500000000000000000000000241360435400500236340ustar00rootroot00000000000000#!/usr/bin/env bash dub-1.19.0/test/describe-project/do-preGenerateCommands.sh000077500000000000000000000000241360435400500234350ustar00rootroot00000000000000#!/usr/bin/env bash dub-1.19.0/test/describe-project/dub.json000066400000000000000000000027571360435400500202370ustar00rootroot00000000000000{ "name": "describe-project", "targetType": "executable", "description": "A test describe project", "authors": ["nobody"], "homepage": "fake.com", "license": "BSD 2-clause", "copyright": "Copyright © 2015, nobody", "mainSourceFile": "src/dummy.d", "sourceFiles-posix": ["./some.a"], "sourceFiles-windows": ["./some.lib"], "dflags": ["--some-dflag"], "lflags": ["--some-lflag"], "libs": ["somelib"], "copyFiles": ["data/dummy.dat"], "versions": ["someVerIdent"], "debugVersions": ["someDebugVerIdent"], "preGenerateCommands-posix": ["./do-preGenerateCommands.sh"], "postGenerateCommands-posix": ["./do-postGenerateCommands.sh"], "preBuildCommands-posix": ["./do-preBuildCommands.sh"], "postBuildCommands-posix": ["./do-postBuildCommands.sh"], "buildRequirements": ["allowWarnings", "disallowInlining"], "buildOptions": ["releaseMode", "debugInfo"], "dependencies": { "describe-dependency-1": { "version": "1.0", "path": "../describe-dependency-1" }, "describe-dependency-2": { "version": "1.0", "path": "../describe-dependency-2" }, "describe-dependency-3": { "version": "1.0", "path": "../describe-dependency-3" } }, "configurations": [ { "name": "my-project-config" } ], "subConfigurations": { "describe-dependency-1": "my-dependency-1-config" }, } dub-1.19.0/test/describe-project/src/000077500000000000000000000000001360435400500173465ustar00rootroot00000000000000dub-1.19.0/test/describe-project/src/dummy.d000066400000000000000000000001371360435400500206470ustar00rootroot00000000000000version (Have_describe_dependency_3) {} version (someVerIdent) {} debug (someDebugVerIdent) {} dub-1.19.0/test/describe-project/views/000077500000000000000000000000001360435400500177145ustar00rootroot00000000000000dub-1.19.0/test/describe-project/views/dummy.d000066400000000000000000000000011360435400500212030ustar00rootroot00000000000000 dub-1.19.0/test/expected-issue1037-output000066400000000000000000000003241360435400500200550ustar00rootroot00000000000000Unresolvable dependencies to package gitcompatibledubpackage: b >=0.0.0 @DIR/b depends on gitcompatibledubpackage ~>1.0.2 issue1037-better-dependency-messages ~master depends on gitcompatibledubpackage 1.0.1 dub-1.19.0/test/feat663-search.sh000077500000000000000000000010311360435400500163060ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh if ${DUB} search 2>/dev/null; then die $LINENO '`dub search` succeeded' fi if ${DUB} search nonexistent123456789package 2>/dev/null; then die $LINENO '`dub search nonexistent123456789package` succeeded' fi if ! OUTPUT=$(${DUB} search '"dub-registry"' -v 2>&1); then die $LINENO '`dub search "dub-registry"` failed' "$OUTPUT" fi if ! grep -q '^dub-registry (.*)\s'<<<"$OUTPUT"; then die $LINENO '`grep -q '"'"'^dub-registry (.*)\s'"'"'` failed' "$OUTPUT" fi dub-1.19.0/test/fetchzip.sh000077500000000000000000000051461360435400500155140ustar00rootroot00000000000000#!/usr/bin/env bash DIR=$(dirname "${BASH_SOURCE[0]}") . "$DIR"/common.sh PORT=$(($$ + 1024)) # PID + 1024 dub remove gitcompatibledubpackage --non-interactive --version=* 2>/dev/null || true "$DUB" build --single "$DIR"/test_registry.d "$DIR"/test_registry --folder="$DIR/issue1336-registry" --port=$PORT & PID=$! sleep 1 trap 'kill $PID 2>/dev/null || true' exit echo "Trying to download gitcompatibledubpackage (1.0.4)" timeout 1s "$DUB" fetch gitcompatibledubpackage --version=1.0.4 --skip-registry=all --registry=http://localhost:$PORT if [ $? -eq 124 ]; then die 'Fetching from responsive registry should not time-out.' fi dub remove gitcompatibledubpackage --non-interactive --version=1.0.4 echo "Downloads should be retried when the zip is corrupted - gitcompatibledubpackage (1.0.3)" zipOut=$(! timeout 1s "$DUB" fetch gitcompatibledubpackage --version=1.0.3 --skip-registry=all --registry=http://localhost:$PORT 2>&1) rc=$? if ! zipCount=$(grep -Fc 'Failed to extract zip archive' <<<"$zipOut") || [ "$zipCount" -lt 3 ] ; then echo '========== +Output was ==========' >&2 echo "$zipOut" >&2 echo '========== -Output was ==========' >&2 die 'DUB should have tried to download the zip archive multiple times.' elif [ $rc -eq 124 ]; then die 'DUB timed out unexpectedly.' fi if dub remove gitcompatibledubpackage --non-interactive --version=* 2>/dev/null; then die 'DUB should not have installed a broken package.' fi echo "HTTP status errors on downloads should be retried - gitcompatibledubpackage (1.0.2)" retryOut=$(! timeout 1s "$DUB" fetch gitcompatibledubpackage --version=1.0.2 --skip-registry=all --registry=http://localhost:$PORT --vverbose 2>&1) rc=$? if ! retryCount=$(echo "$retryOut" | grep -Fc 'Bad Gateway') || [ "$retryCount" -lt 3 ] ; then echo '========== +Output was ==========' >&2 echo "$retryOut" >&2 echo '========== -Output was ==========' >&2 die "DUB should have retried download on server error multiple times, but only tried $retryCount times." elif [ $rc -eq 124 ]; then die 'DUB timed out unexpectedly.' fi if dub remove gitcompatibledubpackage --non-interactive --version=* 2>/dev/null; then die 'DUB should not have installed a package.' fi echo "HTTP status errors on downloads should retry with fallback mirror - gitcompatibledubpackage (1.0.2)" timeout 1s "$DUB" fetch gitcompatibledubpackage --version=1.0.2 --skip-registry=all --registry="http://localhost:$PORT http://localhost:$PORT/fallback" if [ $? -eq 124 ]; then die 'Fetching from responsive registry should not time-out.' fi dub remove gitcompatibledubpackage --non-interactive --version=1.0.2 dub-1.19.0/test/fetchzip.sh.min_frontend000066400000000000000000000000061360435400500201600ustar00rootroot000000000000002.076 dub-1.19.0/test/ignore-hidden-1/000077500000000000000000000000001360435400500162055ustar00rootroot00000000000000dub-1.19.0/test/ignore-hidden-1/.gitignore000066400000000000000000000000461360435400500201750ustar00rootroot00000000000000.dub docs.json __dummy.html *.o *.obj dub-1.19.0/test/ignore-hidden-1/.no_run000066400000000000000000000000001360435400500174740ustar00rootroot00000000000000dub-1.19.0/test/ignore-hidden-1/.no_test000066400000000000000000000000001360435400500176470ustar00rootroot00000000000000dub-1.19.0/test/ignore-hidden-1/dub.json000066400000000000000000000000401360435400500176440ustar00rootroot00000000000000{ "name": "ignore-hidden-1", } dub-1.19.0/test/ignore-hidden-1/source/000077500000000000000000000000001360435400500175055ustar00rootroot00000000000000dub-1.19.0/test/ignore-hidden-1/source/.hidden.d000066400000000000000000000002131360435400500211570ustar00rootroot00000000000000// need module declarations as '.' is not allowed in module names module hidden; static assert(0, "Dub should not compile "~__FILE__~"."); dub-1.19.0/test/ignore-hidden-1/source/app.d000066400000000000000000000000201360435400500204220ustar00rootroot00000000000000void main() { } dub-1.19.0/test/ignore-hidden-2/000077500000000000000000000000001360435400500162065ustar00rootroot00000000000000dub-1.19.0/test/ignore-hidden-2/.gitignore000066400000000000000000000000461360435400500201760ustar00rootroot00000000000000.dub docs.json __dummy.html *.o *.obj dub-1.19.0/test/ignore-hidden-2/.no_run000066400000000000000000000000001360435400500174750ustar00rootroot00000000000000dub-1.19.0/test/ignore-hidden-2/.no_test000066400000000000000000000000001360435400500176500ustar00rootroot00000000000000dub-1.19.0/test/ignore-hidden-2/dub.json000066400000000000000000000001061360435400500176500ustar00rootroot00000000000000{ "name": "ignore-hidden-2", "sourceFiles": ["source/.hidden.d"], } dub-1.19.0/test/ignore-hidden-2/source/000077500000000000000000000000001360435400500175065ustar00rootroot00000000000000dub-1.19.0/test/ignore-hidden-2/source/.hidden.d000066400000000000000000000000171360435400500211620ustar00rootroot00000000000000module hidden; dub-1.19.0/test/ignore-hidden-2/source/app.d000066400000000000000000000000401360435400500204250ustar00rootroot00000000000000import hidden; void main() { } dub-1.19.0/test/interactive-remove.sh000077500000000000000000000025521360435400500175060ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh $DUB fetch dub --version=1.9.0 && [ -d $HOME/.dub/packages/dub-1.9.0/dub ] $DUB fetch dub --version=1.10.0 && [ -d $HOME/.dub/packages/dub-1.10.0/dub ] if $DUB remove dub --non-interactive 2>/dev/null; then die $LINENO 'Non-interactive remove should fail' fi echo 1 | $DUB remove dub | tr -d '\n' | grep --ignore-case 'select.*1\.9\.0.*1\.10\.0.*' if [ -d $HOME/.dub/packages/dub-1.9.0/dub ]; then die $LINENO 'Failed to remove dub-1.9.0' fi $DUB fetch dub --version=1.9.0 && [ -d $HOME/.dub/packages/dub-1.9.0/dub ] # EOF aborts remove echo -xn '' | $DUB remove dub if [ ! -d $HOME/.dub/packages/dub-1.9.0/dub ] || [ ! -d $HOME/.dub/packages/dub-1.10.0/dub ]; then die $LINENO 'Aborted dub still removed a package' fi # validates input echo -e 'abc\n4\n-1\n3' | $DUB remove dub if [ -d $HOME/.dub/packages/dub-1.9.0/dub ] || [ -d $HOME/.dub/packages/dub-1.10.0/dub ]; then die $LINENO 'Failed to remove all version of dub' fi $DUB fetch dub --version=1.9.0 && [ -d $HOME/.dub/packages/dub-1.9.0/dub ] $DUB fetch dub@1.10.0 && [ -d $HOME/.dub/packages/dub-1.10.0/dub ] # is non-interactive with --version= $DUB remove dub --version=\* if [ -d $HOME/.dub/packages/dub-1.9.0/dub ] || [ -d $HOME/.dub/packages/dub-1.10.0/dub ]; then die $LINENO 'Failed to non-interactively remove specified versions' fi dub-1.19.0/test/issue1003-check-empty-ld-flags.sh000077500000000000000000000002261360435400500212240ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue1003-check-empty-ld-flags ${DUB} build --compiler=${DC} --force dub-1.19.0/test/issue1003-check-empty-ld-flags/000077500000000000000000000000001360435400500206655ustar00rootroot00000000000000dub-1.19.0/test/issue1003-check-empty-ld-flags/dub.json000066400000000000000000000002441360435400500223320ustar00rootroot00000000000000{ "authors": [ "--" ], "copyright": "Copyright © 2019, --", "description": "--", "license": "--", "name": "issue1003-empty-ld-flags", "lflags": [""] } dub-1.19.0/test/issue1003-check-empty-ld-flags/source/000077500000000000000000000000001360435400500221655ustar00rootroot00000000000000dub-1.19.0/test/issue1003-check-empty-ld-flags/source/app.d000066400000000000000000000001311360435400500231050ustar00rootroot00000000000000import std.stdio; void main() { writeln("Edit source/app.d to start your project."); } dub-1.19.0/test/issue1004-override-config.sh000077500000000000000000000002361360435400500204100ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue1004-override-config ${DUB} build --bare main --override-config a/success dub-1.19.0/test/issue1004-override-config/000077500000000000000000000000001360435400500200505ustar00rootroot00000000000000dub-1.19.0/test/issue1004-override-config/.no_build000066400000000000000000000000001360435400500216320ustar00rootroot00000000000000dub-1.19.0/test/issue1004-override-config/a/000077500000000000000000000000001360435400500202705ustar00rootroot00000000000000dub-1.19.0/test/issue1004-override-config/a/a.d000066400000000000000000000000331360435400500206510ustar00rootroot00000000000000module a; void test() { } dub-1.19.0/test/issue1004-override-config/a/dub.sdl000066400000000000000000000001441360435400500215450ustar00rootroot00000000000000name "a" configuration "fail" { } configuration "success" { sourceFiles "a.d" importPaths "." } dub-1.19.0/test/issue1004-override-config/main/000077500000000000000000000000001360435400500207745ustar00rootroot00000000000000dub-1.19.0/test/issue1004-override-config/main/dub.sdl000066400000000000000000000000471360435400500222530ustar00rootroot00000000000000name "main" dependency "a" version="*" dub-1.19.0/test/issue1004-override-config/main/source/000077500000000000000000000000001360435400500222745ustar00rootroot00000000000000dub-1.19.0/test/issue1004-override-config/main/source/main.d000066400000000000000000000000441360435400500233630ustar00rootroot00000000000000import a; void main() { test(); } dub-1.19.0/test/issue1005-configuration-resolution.sh000077500000000000000000000002131360435400500223720ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue1005-configuration-resolution ${DUB} build --bare main dub-1.19.0/test/issue1005-configuration-resolution/000077500000000000000000000000001360435400500220375ustar00rootroot00000000000000dub-1.19.0/test/issue1005-configuration-resolution/.no_build000066400000000000000000000000001360435400500236210ustar00rootroot00000000000000dub-1.19.0/test/issue1005-configuration-resolution/a/000077500000000000000000000000001360435400500222575ustar00rootroot00000000000000dub-1.19.0/test/issue1005-configuration-resolution/a/dub.sdl000066400000000000000000000002061360435400500235330ustar00rootroot00000000000000name "a" dependency "b" version="*" configuration "x" { subConfiguration "b" "x" } configuration "y" { subConfiguration "b" "y" } dub-1.19.0/test/issue1005-configuration-resolution/b/000077500000000000000000000000001360435400500222605ustar00rootroot00000000000000dub-1.19.0/test/issue1005-configuration-resolution/b/dub.sdl000066400000000000000000000000661360435400500235400ustar00rootroot00000000000000name "b" configuration "x" { } configuration "y" { }dub-1.19.0/test/issue1005-configuration-resolution/b/source/000077500000000000000000000000001360435400500235605ustar00rootroot00000000000000dub-1.19.0/test/issue1005-configuration-resolution/b/source/b.d000066400000000000000000000000311360435400500241400ustar00rootroot00000000000000module b; void foo() {} dub-1.19.0/test/issue1005-configuration-resolution/c/000077500000000000000000000000001360435400500222615ustar00rootroot00000000000000dub-1.19.0/test/issue1005-configuration-resolution/c/dub.sdl000066400000000000000000000000441360435400500235350ustar00rootroot00000000000000name "c" dependency "a" version="*" dub-1.19.0/test/issue1005-configuration-resolution/main/000077500000000000000000000000001360435400500227635ustar00rootroot00000000000000dub-1.19.0/test/issue1005-configuration-resolution/main/dub.sdl000066400000000000000000000001351360435400500242400ustar00rootroot00000000000000name "main" dependency "b" version="*" dependency "c" version="*" subConfiguration "b" "y" dub-1.19.0/test/issue1005-configuration-resolution/main/source/000077500000000000000000000000001360435400500242635ustar00rootroot00000000000000dub-1.19.0/test/issue1005-configuration-resolution/main/source/app.d000066400000000000000000000000431360435400500252050ustar00rootroot00000000000000import b; void main() { foo(); } dub-1.19.0/test/issue1024-selective-upgrade.sh000077500000000000000000000007551360435400500207460ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue1024-selective-upgrade echo "{\"fileVersion\": 1,\"versions\": {\"a\": \"1.0.0\", \"b\": \"1.0.0\"}}" > main/dub.selections.json $DUB upgrade --bare --root=main a if ! grep -c -e "\"a\": \"1.0.1\"" main/dub.selections.json; then die $LINENO "Specified dependency was not upgraded." fi if grep -c -e "\"b\": \"1.0.1\"" main/dub.selections.json; then die $LINENO "Non-specified dependency got upgraded." fi dub-1.19.0/test/issue1024-selective-upgrade/000077500000000000000000000000001360435400500204005ustar00rootroot00000000000000dub-1.19.0/test/issue1024-selective-upgrade/.no_build000066400000000000000000000000001360435400500221620ustar00rootroot00000000000000dub-1.19.0/test/issue1024-selective-upgrade/a-1.0.0/000077500000000000000000000000001360435400500212525ustar00rootroot00000000000000dub-1.19.0/test/issue1024-selective-upgrade/a-1.0.0/dub.sdl000066400000000000000000000000311360435400500225220ustar00rootroot00000000000000name "a" version "1.0.0" dub-1.19.0/test/issue1024-selective-upgrade/a-1.0.1/000077500000000000000000000000001360435400500212535ustar00rootroot00000000000000dub-1.19.0/test/issue1024-selective-upgrade/a-1.0.1/dub.sdl000066400000000000000000000000311360435400500225230ustar00rootroot00000000000000name "a" version "1.0.1" dub-1.19.0/test/issue1024-selective-upgrade/b-1.0.0/000077500000000000000000000000001360435400500212535ustar00rootroot00000000000000dub-1.19.0/test/issue1024-selective-upgrade/b-1.0.0/dub.sdl000066400000000000000000000000311360435400500225230ustar00rootroot00000000000000name "b" version "1.0.0" dub-1.19.0/test/issue1024-selective-upgrade/b-1.0.1/000077500000000000000000000000001360435400500212545ustar00rootroot00000000000000dub-1.19.0/test/issue1024-selective-upgrade/b-1.0.1/dub.sdl000066400000000000000000000000311360435400500225240ustar00rootroot00000000000000name "b" version "1.0.1" dub-1.19.0/test/issue1024-selective-upgrade/main/000077500000000000000000000000001360435400500213245ustar00rootroot00000000000000dub-1.19.0/test/issue1024-selective-upgrade/main/dub.sdl000066400000000000000000000001161360435400500226000ustar00rootroot00000000000000name "test" dependency "a" version="~>1.0.0" dependency "b" version="~>1.0.0" dub-1.19.0/test/issue103-single-file-package-json.d000066400000000000000000000002111360435400500216020ustar00rootroot00000000000000/+ dub.json: { "name": "single-file-test" } +/ module hello; void main() { import std.stdio : writeln; writeln("Hello, World!"); } dub-1.19.0/test/issue103-single-file-package-no-ext000077500000000000000000000003361360435400500216340ustar00rootroot00000000000000#!../bin/dub /+ dub.sdl: name "single-file-test" +/ module hello; void main(string[] args) { import std.stdio : writeln; assert(args.length == 4 && args[1 .. 4] == ["foo", "--", "bar"]); writeln("Hello, World!"); } dub-1.19.0/test/issue103-single-file-package-w-dep.d000066400000000000000000000002371360435400500216550ustar00rootroot00000000000000/+ dub.sdl: name "single-file-test" dependency "sourcelib-simple" path="1-sourceLib-simple" +/ module hello; import sourcelib.app; void main() { entry(); } dub-1.19.0/test/issue103-single-file-package.d000077500000000000000000000003361360435400500206460ustar00rootroot00000000000000#!../bin/dub /+ dub.sdl: name "single-file-test" +/ module hello; void main(string[] args) { import std.stdio : writeln; assert(args.length == 4 && args[1 .. 4] == ["foo", "--", "bar"]); writeln("Hello, World!"); } dub-1.19.0/test/issue103-single-file-package.sh000077500000000000000000000016661360435400500210440ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR} rm -f single-file-test ${DUB} run --single issue103-single-file-package-json.d --compiler=${DC} if [ ! -f single-file-test ]; then die $LINENO 'Normal invocation did not produce a binary in the current directory' fi rm single-file-test ./issue103-single-file-package.d foo -- bar ${DUB} ./issue103-single-file-package foo -- bar ./issue103-single-file-package-no-ext foo -- bar ${DUB} issue103-single-file-package-w-dep.d if [ -f single-file-test ]; then die $LINENO 'Shebang invocation produced binary in current directory' fi if ! { ${DUB} run --single issue103-single-file-package-w-dep.d --temp-build 2>&1 || true; } | grep -cF "To force a rebuild"; then echo "Invocation triggered unnecessary rebuild." exit 1 fi if ${DUB} "issue103-single-file-package-error.d" 2> /dev/null; then echo "Invalid package comment syntax did not trigger an error." exit 1 fi dub-1.19.0/test/issue1037-better-dependency-messages.sh000077500000000000000000000010731360435400500225420ustar00rootroot00000000000000#!/bin/bash set -e -o pipefail cd ${CURR_DIR}/issue1037-better-dependency-messages temp_file=$(mktemp $(basename $0).XXXXXX) temp_file2=$(mktemp $(basename $0).XXXXXX) expected_file="$CURR_DIR/expected-issue1037-output" function cleanup { rm -f $temp_file rm -f $temp_file2 } trap cleanup EXIT sed "s#DIR#$CURR_DIR/issue1037-better-dependency-messages#" "$expected_file" > "$temp_file2" $DUB upgrade 2>$temp_file && exit 1 # dub upgrade should fail if ! diff "$temp_file2" "$temp_file"; then die 'output not containing conflict information' fi exit 0 dub-1.19.0/test/issue1037-better-dependency-messages/000077500000000000000000000000001360435400500222025ustar00rootroot00000000000000dub-1.19.0/test/issue1037-better-dependency-messages/.no_build000066400000000000000000000000001360435400500237640ustar00rootroot00000000000000dub-1.19.0/test/issue1037-better-dependency-messages/.no_run000066400000000000000000000000001360435400500234710ustar00rootroot00000000000000dub-1.19.0/test/issue1037-better-dependency-messages/.no_test000066400000000000000000000000001360435400500236440ustar00rootroot00000000000000dub-1.19.0/test/issue1037-better-dependency-messages/b/000077500000000000000000000000001360435400500224235ustar00rootroot00000000000000dub-1.19.0/test/issue1037-better-dependency-messages/b/dub.json000066400000000000000000000001161360435400500240660ustar00rootroot00000000000000{ "name": "b", "dependencies": { "gitcompatibledubpackage": "~>1.0.2" } }dub-1.19.0/test/issue1037-better-dependency-messages/dub.json000066400000000000000000000002371360435400500236510ustar00rootroot00000000000000{ "name": "issue1037-better-dependency-messages", "dependencies": { "gitcompatibledubpackage": "1.0.1", "b": { "path": "b", "version": "*" } } }dub-1.19.0/test/issue1070-init-mistakes-dirs-as-files.sh000077500000000000000000000002621360435400500225510ustar00rootroot00000000000000#!/bin/bash cd ${CURR_DIR}/issue1070-init-mistakes-dirs-as-files ${DUB} init 2>&1 | grep -c "The target directory already contains a 'source/' directory. Aborting." > /dev/nulldub-1.19.0/test/issue1070-init-mistakes-dirs-as-files/000077500000000000000000000000001360435400500222125ustar00rootroot00000000000000dub-1.19.0/test/issue1070-init-mistakes-dirs-as-files/.no_build000066400000000000000000000000001360435400500237740ustar00rootroot00000000000000dub-1.19.0/test/issue1070-init-mistakes-dirs-as-files/.no_run000066400000000000000000000000001360435400500235010ustar00rootroot00000000000000dub-1.19.0/test/issue1070-init-mistakes-dirs-as-files/.no_test000066400000000000000000000000001360435400500236540ustar00rootroot00000000000000dub-1.19.0/test/issue1070-init-mistakes-dirs-as-files/source/000077500000000000000000000000001360435400500235125ustar00rootroot00000000000000dub-1.19.0/test/issue1070-init-mistakes-dirs-as-files/source/.empty000066400000000000000000000000001360435400500246370ustar00rootroot00000000000000dub-1.19.0/test/issue1091-bogus-rebuild.sh000077500000000000000000000004211360435400500200730ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/1-exec-simple rm -f dub.selections.json ${DUB} build --compiler=${DC} 2>&1 | grep -e 'building configuration' -c ${DUB} build --compiler=${DC} 2>&1 | { ! grep -e 'building configuration' -c; } dub-1.19.0/test/issue1117-extra-dependency-files.sh000077500000000000000000000007471360435400500217010ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue1117-extra-dependency-files if ! { ${DUB} build 2>&1 || true; } | grep -cF 'building configuration'; then die $LINENO 'Build was not executed.' fi if ! { ${DUB} build 2>&1 || true; } | grep -cF 'is up to date'; then die $LINENO 'Build was executed.' fi touch ./dependency.txt if ! { ${DUB} build 2>&1 || true; } | grep -cF 'building configuration'; then die $LINENO 'Build was not executed.' fi dub-1.19.0/test/issue1117-extra-dependency-files/000077500000000000000000000000001360435400500213325ustar00rootroot00000000000000dub-1.19.0/test/issue1117-extra-dependency-files/.gitignore000066400000000000000000000000701360435400500233170ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ *.exe *.o *.obj *.lst dub-1.19.0/test/issue1117-extra-dependency-files/.no_build000066400000000000000000000000001360435400500231140ustar00rootroot00000000000000dub-1.19.0/test/issue1117-extra-dependency-files/dependency.txt000066400000000000000000000000051360435400500242040ustar00rootroot00000000000000Hellodub-1.19.0/test/issue1117-extra-dependency-files/dub.json000066400000000000000000000001001360435400500227660ustar00rootroot00000000000000{ "name": "test", "extraDependencyFiles": ["dependency.txt"] }dub-1.19.0/test/issue1117-extra-dependency-files/source/000077500000000000000000000000001360435400500226325ustar00rootroot00000000000000dub-1.19.0/test/issue1117-extra-dependency-files/source/app.d000066400000000000000000000000151360435400500235530ustar00rootroot00000000000000void main(){}dub-1.19.0/test/issue1136-temp-copy-files.sh000077500000000000000000000001671360435400500203540ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue1136-temp-copy-files "$DUB" app.d dub-1.19.0/test/issue1136-temp-copy-files/000077500000000000000000000000001360435400500200115ustar00rootroot00000000000000dub-1.19.0/test/issue1136-temp-copy-files/.no_build000066400000000000000000000000001360435400500215730ustar00rootroot00000000000000dub-1.19.0/test/issue1136-temp-copy-files/app.d000066400000000000000000000004361360435400500207410ustar00rootroot00000000000000/+ dub.sdl: name "app" dependency "mylib" path="./mylib" +/ import std.exception: enforce; import std.file: exists, thisExePath; import std.path: dirName, buildPath; void main() { string filePath = buildPath(thisExePath.dirName, "helloworld.txt"); enforce(filePath.exists); }dub-1.19.0/test/issue1136-temp-copy-files/mylib/000077500000000000000000000000001360435400500211255ustar00rootroot00000000000000dub-1.19.0/test/issue1136-temp-copy-files/mylib/dub.sdl000066400000000000000000000000731360435400500224030ustar00rootroot00000000000000name "mylib" copyFiles "./helloworld.txt" targetType "none"dub-1.19.0/test/issue1136-temp-copy-files/mylib/helloworld.txt000066400000000000000000000000141360435400500240340ustar00rootroot00000000000000hello world!dub-1.19.0/test/issue1158-stdin-for-single-files.sh000077500000000000000000000003731360435400500216260ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue1158-stdin-for-single-files if ! { cat stdin.d | ${DUB} - --value=v 2>&1 || true; } | grep -cF '["--value=v"]'; then die $LINENO 'Stdin for single files failed.' fidub-1.19.0/test/issue1158-stdin-for-single-files/000077500000000000000000000000001360435400500212645ustar00rootroot00000000000000dub-1.19.0/test/issue1158-stdin-for-single-files/.no_build000066400000000000000000000000001360435400500230460ustar00rootroot00000000000000dub-1.19.0/test/issue1158-stdin-for-single-files/stdin.d000066400000000000000000000001541360435400500225520ustar00rootroot00000000000000/+ dub.sdl: name "hello" +/ void main(string[] args) { import std.stdio : writeln; writeln(args[1..$]); }dub-1.19.0/test/issue1180-local-cache-broken.sh000077500000000000000000000014701360435400500207450ustar00rootroot00000000000000#!/usr/bin/env bash DIR=$(dirname "${BASH_SOURCE[0]}") . "$DIR"/common.sh PORT=$(($$ + 1024)) # PID + 1024 "$DUB" remove maven-dubpackage --root="$DIR/issue1180-local-cache-broken" --non-interactive --version=* 2>/dev/null || true "$DUB" build --single "$DIR"/test_registry.d "$DIR"/test_registry --folder="$DIR/issue1416-maven-repo-pkg-supplier" --port=$PORT & PID=$! sleep 1 trap 'kill $PID 2>/dev/null || true' exit echo "Trying to download maven-dubpackage (1.0.5)" "$DUB" upgrade --root="$DIR/issue1180-local-cache-broken" --cache=local --skip-registry=all --registry=mvn+http://localhost:$PORT/maven/release/dubpackages if ! "$DUB" remove maven-dubpackage --root="$DIR/issue1180-local-cache-broken" --non-interactive --version=1.0.5 2>/dev/null; then die 'DUB did not install package from maven registry.' fi dub-1.19.0/test/issue1180-local-cache-broken.sh.min_frontend000066400000000000000000000000061360435400500234150ustar00rootroot000000000000002.076 dub-1.19.0/test/issue1180-local-cache-broken/000077500000000000000000000000001360435400500204045ustar00rootroot00000000000000dub-1.19.0/test/issue1180-local-cache-broken/.gitignore000066400000000000000000000000231360435400500223670ustar00rootroot00000000000000test *.o *.exe .dubdub-1.19.0/test/issue1180-local-cache-broken/.no_build000066400000000000000000000000001360435400500221660ustar00rootroot00000000000000dub-1.19.0/test/issue1180-local-cache-broken/dub.json000066400000000000000000000001111360435400500220420ustar00rootroot00000000000000{ "name": "test", "dependencies": { "maven-dubpackage": "1.0.5" } }dub-1.19.0/test/issue1180-local-cache-broken/source/000077500000000000000000000000001360435400500217045ustar00rootroot00000000000000dub-1.19.0/test/issue1180-local-cache-broken/source/app.d000066400000000000000000000000151360435400500226250ustar00rootroot00000000000000void main(){}dub-1.19.0/test/issue1194-warn-wrong-subconfig.sh000077500000000000000000000017411360435400500214200ustar00rootroot00000000000000#!/usr/bin/env bash set -e OUTPUT=`${DUB} build --root ${CURR_DIR}/issue1194-warn-wrong-subconfig 2>&1 || true` # make sure the proper errors occur in the output echo $OUTPUT | grep -c "sub configuration directive \"bar\" -> \"baz\" references a package that is not specified as a dependency" > /dev/null echo $OUTPUT | grep -c "sub configuration directive \"staticlib-simple\" -> \"foo\" references a configuration that does not exist" > /dev/null ! echo $OUTPUT | grep -c "sub configuration directive \"sourcelib-simple\" -> \"library\" references a package that is not specified as a dependency" > /dev/null ! echo $OUTPUT | grep -c "sub configuration directive \"sourcelib-simple\" -> \"library\" references a configuration that does not exist" > /dev/null # make sure no bogs warnings are issued for packages with no sub configuration directives OUTPUT=`${DUB} build --root ${CURR_DIR}/1-exec-simple 2>&1` ! echo $OUTPUT | grep -c "sub configuration directive.*references" > /dev/null dub-1.19.0/test/issue1194-warn-wrong-subconfig/000077500000000000000000000000001360435400500210565ustar00rootroot00000000000000dub-1.19.0/test/issue1194-warn-wrong-subconfig/.no_build000066400000000000000000000000001360435400500226400ustar00rootroot00000000000000dub-1.19.0/test/issue1194-warn-wrong-subconfig/dub.sdl000066400000000000000000000004201360435400500223300ustar00rootroot00000000000000name "test" dependency "staticlib-simple" path="../1-staticLib-simple" dependency "sourcelib-simple" path="../1-sourceLib-simple" targetType "executable" subConfiguration "staticlib-simple" "foo" subConfiguration "bar" "baz" subConfiguration "sourcelib-simple" "library" dub-1.19.0/test/issue1194-warn-wrong-subconfig/source/000077500000000000000000000000001360435400500223565ustar00rootroot00000000000000dub-1.19.0/test/issue1194-warn-wrong-subconfig/source/app.d000066400000000000000000000000171360435400500233010ustar00rootroot00000000000000void main() {} dub-1.19.0/test/issue1262-version-inheritance-diamond/000077500000000000000000000000001360435400500223615ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance-diamond/.gitignore000066400000000000000000000005341360435400500243530ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ issue1262-version-inheritance-diamond issue1262-version-inheritance-diamond.so issue1262-version-inheritance-diamond.dylib issue1262-version-inheritance-diamond.dll issue1262-version-inheritance-diamond.a issue1262-version-inheritance-diamond.lib issue1262-version-inheritance-diamond-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/issue1262-version-inheritance-diamond/.no_run000066400000000000000000000000001360435400500236500ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance-diamond/.no_test000066400000000000000000000000001360435400500240230ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance-diamond/daughter/000077500000000000000000000000001360435400500241645ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance-diamond/daughter/.gitignore000066400000000000000000000002101360435400500261450ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ daughter.so daughter.dylib daughter.dll daughter.a daughter.lib daughter-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/issue1262-version-inheritance-diamond/daughter/dub.sdl000066400000000000000000000001131360435400500254350ustar00rootroot00000000000000name "daughter" versions "Daughter" dependency "diamond" path="../diamond" dub-1.19.0/test/issue1262-version-inheritance-diamond/daughter/source/000077500000000000000000000000001360435400500254645ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance-diamond/daughter/source/dummy.d000066400000000000000000000004701360435400500267650ustar00rootroot00000000000000module daughter.dummy; version (Parent) {} else static assert(0, "Expected Parent to be set"); version (Daughter) {} else static assert(0, "Expected Daughter to be set"); version (Son) {} else static assert(0, "Expected Son to be set"); version (Diamond) {} else static assert(0, "Expected Diamond to be set"); dub-1.19.0/test/issue1262-version-inheritance-diamond/diamond/000077500000000000000000000000001360435400500237745ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance-diamond/diamond/.gitignore000066400000000000000000000002021360435400500257560ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ diamond.so diamond.dylib diamond.dll diamond.a diamond.lib diamond-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/issue1262-version-inheritance-diamond/diamond/dub.sdl000066400000000000000000000000421360435400500252460ustar00rootroot00000000000000name "diamond" versions "Diamond" dub-1.19.0/test/issue1262-version-inheritance-diamond/diamond/source/000077500000000000000000000000001360435400500252745ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance-diamond/diamond/source/dummy.d000066400000000000000000000004671360435400500266030ustar00rootroot00000000000000module diamond.dummy; version (Parent) {} else static assert(0, "Expected Parent to be set"); version (Daughter) {} else static assert(0, "Expected Daughter to be set"); version (Son) {} else static assert(0, "Expected Son to be set"); version (Diamond) {} else static assert(0, "Expected Diamond to be set"); dub-1.19.0/test/issue1262-version-inheritance-diamond/dub.sdl000066400000000000000000000002011360435400500236300ustar00rootroot00000000000000name "issue1262-version-inheritance-diamond" versions "Parent" dependency "daughter" path="daughter" dependency "son" path="son" dub-1.19.0/test/issue1262-version-inheritance-diamond/son/000077500000000000000000000000001360435400500231605ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance-diamond/son/.gitignore000066400000000000000000000001521360435400500251460ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ son.so son.dylib son.dll son.a son.lib son-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/issue1262-version-inheritance-diamond/son/dub.sdl000066400000000000000000000001011360435400500244260ustar00rootroot00000000000000name "son" versions "Son" dependency "diamond" path="../diamond" dub-1.19.0/test/issue1262-version-inheritance-diamond/son/source/000077500000000000000000000000001360435400500244605ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance-diamond/son/source/dummy.d000066400000000000000000000004631360435400500257630ustar00rootroot00000000000000module son.dummy; version (Parent) {} else static assert(0, "Expected Parent to be set"); version (Daughter) {} else static assert(0, "Expected Daughter to be set"); version (Son) {} else static assert(0, "Expected Son to be set"); version (Diamond) {} else static assert(0, "Expected Diamond to be set"); dub-1.19.0/test/issue1262-version-inheritance-diamond/source/000077500000000000000000000000001360435400500236615ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance-diamond/source/app.d000066400000000000000000000004611360435400500246070ustar00rootroot00000000000000version (Parent) {} else static assert(0, "Expected Parent to be set"); version (Daughter) {} else static assert(0, "Expected Daughter to be set"); version (Son) {} else static assert(0, "Expected Son to be set"); version (Diamond) {} else static assert(0, "Expected Diamond to be set"); void main() { } dub-1.19.0/test/issue1262-version-inheritance/000077500000000000000000000000001360435400500207505ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance/.gitignore000066400000000000000000000004441360435400500227420ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ issue1262-version-inheritance issue1262-version-inheritance.so issue1262-version-inheritance.dylib issue1262-version-inheritance.dll issue1262-version-inheritance.a issue1262-version-inheritance.lib issue1262-version-inheritance-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/issue1262-version-inheritance/.no_run000066400000000000000000000000001360435400500222370ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance/.no_test000066400000000000000000000000001360435400500224120ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance/daughter/000077500000000000000000000000001360435400500225535ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance/daughter/.gitignore000066400000000000000000000002101360435400500245340ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ daughter.so daughter.dylib daughter.dll daughter.a daughter.lib daughter-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/issue1262-version-inheritance/daughter/dub.sdl000066400000000000000000000000451360435400500240300ustar00rootroot00000000000000name "daughter" versions "Daughter" dub-1.19.0/test/issue1262-version-inheritance/daughter/source/000077500000000000000000000000001360435400500240535ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance/daughter/source/dummy.d000066400000000000000000000003511360435400500253520ustar00rootroot00000000000000module daughter.dummy; version (Parent) {} else static assert(0, "Expected Parent to be set"); version (Daughter) {} else static assert(0, "Expected Daughter to be set"); version (Son) static assert(0, "Expected Son to no be set"); dub-1.19.0/test/issue1262-version-inheritance/dub.sdl000066400000000000000000000001711360435400500222250ustar00rootroot00000000000000name "issue1262-version-inheritance" versions "Parent" dependency "daughter" path="daughter" dependency "son" path="son" dub-1.19.0/test/issue1262-version-inheritance/son/000077500000000000000000000000001360435400500215475ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance/son/.gitignore000066400000000000000000000001521360435400500235350ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ son.so son.dylib son.dll son.a son.lib son-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/issue1262-version-inheritance/son/dub.sdl000066400000000000000000000000321360435400500230200ustar00rootroot00000000000000name "son" versions "Son" dub-1.19.0/test/issue1262-version-inheritance/son/source/000077500000000000000000000000001360435400500230475ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance/son/source/dummy.d000066400000000000000000000003451360435400500243510ustar00rootroot00000000000000module son.dummy; version (Parent) {} else static assert(0, "Expected Parent to be set"); version (Daughter) static assert(0, "Expected Daughter to not be set"); version (Son) {} else static assert(0, "Expected Son to be set"); dub-1.19.0/test/issue1262-version-inheritance/source/000077500000000000000000000000001360435400500222505ustar00rootroot00000000000000dub-1.19.0/test/issue1262-version-inheritance/source/app.d000066400000000000000000000003471360435400500232010ustar00rootroot00000000000000version (Parent) {} else static assert(0, "Expected Parent to be set"); version (Daughter) {} else static assert(0, "Expected Daughter to be set"); version (Son) {} else static assert(0, "Expected Son to be set"); void main() { } dub-1.19.0/test/issue130-unicode-СНАЯАСТЕЯЅ/000077500000000000000000000000001360435400500255015ustar00rootroot00000000000000dub-1.19.0/test/issue130-unicode-СНАЯАСТЕЯЅ/dub.sdl000066400000000000000000000000151360435400500267530ustar00rootroot00000000000000name "tests" dub-1.19.0/test/issue130-unicode-СНАЯАСТЕЯЅ/source/000077500000000000000000000000001360435400500270015ustar00rootroot00000000000000dub-1.19.0/test/issue130-unicode-СНАЯАСТЕЯЅ/source/app.d000066400000000000000000000000711360435400500277240ustar00rootroot00000000000000import std.stdio; void main() { writeln("Success."); } dub-1.19.0/test/issue1336-registry/000077500000000000000000000000001360435400500166465ustar00rootroot00000000000000dub-1.19.0/test/issue1336-registry/.gitignore000066400000000000000000000003041360435400500206330ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ issue1336-registry.so issue1336-registry.dylib issue1336-registry.dll issue1336-registry.a issue1336-registry.lib issue1336-registry-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/issue1336-registry/.no_build000066400000000000000000000000001360435400500204300ustar00rootroot00000000000000dub-1.19.0/test/issue1336-registry/api/000077500000000000000000000000001360435400500174175ustar00rootroot00000000000000dub-1.19.0/test/issue1336-registry/api/packages/000077500000000000000000000000001360435400500211755ustar00rootroot00000000000000infos__packages=%5B%22gitcompatibledubpackage%22%5D&include_dependencies=true&minimize=true000066400000000000000000000006331360435400500420640ustar00rootroot00000000000000dub-1.19.0/test/issue1336-registry/api/packages{ "gitcompatibledubpackage": {"versions":[{"configurations":[{"name":"exe"},{"name":"lib"}],"version":"~master","name":"gitcompatibledubpackage"},{"version":"1.0.1","name":"gitcompatibledubpackage"},{"version":"1.0.2","name":"gitcompatibledubpackage"},{"version":"1.0.3","name":"gitcompatibledubpackage"},{"configurations":[{"name":"exe"},{"name":"lib"}],"version":"1.0.4","name":"gitcompatibledubpackage"}]} }dub-1.19.0/test/issue1336-registry/packages/000077500000000000000000000000001360435400500204245ustar00rootroot00000000000000dub-1.19.0/test/issue1336-registry/packages/gitcompatibledubpackage/000077500000000000000000000000001360435400500252565ustar00rootroot00000000000000dub-1.19.0/test/issue1336-registry/packages/gitcompatibledubpackage/1.0.2.zip0000777000000000000000000000000013604354005002761721.0.4.zipustar00rootroot00000000000000dub-1.19.0/test/issue1336-registry/packages/gitcompatibledubpackage/1.0.3.zip000066400000000000000000000000131360435400500264330ustar00rootroot00000000000000BROKEN ZIP dub-1.19.0/test/issue1336-registry/packages/gitcompatibledubpackage/1.0.4.zip000066400000000000000000000037711360435400500264520ustar00rootroot00000000000000PK QZ2K gitcompatibledubpackage-1.0.4/UT YPK QZ2KNj*' gitcompatibledubpackage-1.0.4/README.mdUT Y=j0 DP{,eS)D(k7,п_٥=C̴0v3I9MR}%i^NuZ 'u.d SjLH Ԛ%J >O;ފ]'JFʳmˌp  ˦ Oܭ`78NN:QB1i?{;!jsa{XȺ#S0Wr!`b5~s[~)k"'ֹBSP>jzN,ޅf^KIl,;Mbfz},ʩ.NKIdz+NnA`v՜; ^5};6bEI򴛹,OU_}SЩ#)@ά PK QZ2KV\% gitcompatibledubpackage-1.0.4/hello.dUT YO)IUHɷ*LQM(.)KUH,J/R܂= ei(yLQp uRҴPK QZ2K% gitcompatibledubpackage-1.0.4/subdir/UT YPK QZ2KOn+ gitcompatibledubpackage-1.0.4/subdir/file.dUT Ym10 Ew"`{6`(vJU {FM9mC2\pyƓLRULӎ>x5bF@iE)5؋PK QZ2K gitcompatibledubpackage-1.0.4/UT YPK QZ2KNj*' Egitcompatibledubpackage-1.0.4/README.mdUT YPK QZ2K4E% Sgitcompatibledubpackage-1.0.4/dub.sdlUT YPK QZ2KV\% gitcompatibledubpackage-1.0.4/hello.dUT YPK QZ2K% gitcompatibledubpackage-1.0.4/subdir/UT YPK QZ2KOn+ gitcompatibledubpackage-1.0.4/subdir/file.dUT YPK)(9e3972be4c63790c32257220f40c0af7dc41bec5dub-1.19.0/test/issue1350-transitive-none-deps/000077500000000000000000000000001360435400500210505ustar00rootroot00000000000000dub-1.19.0/test/issue1350-transitive-none-deps/.gitignore000066400000000000000000000001651360435400500230420ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ test test.so test.dylib test.dll test.a test.lib test-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/issue1350-transitive-none-deps/.no_run000066400000000000000000000000001360435400500223370ustar00rootroot00000000000000dub-1.19.0/test/issue1350-transitive-none-deps/.no_test000066400000000000000000000000001360435400500225120ustar00rootroot00000000000000dub-1.19.0/test/issue1350-transitive-none-deps/common-dep/000077500000000000000000000000001360435400500231065ustar00rootroot00000000000000dub-1.19.0/test/issue1350-transitive-none-deps/common-dep/common.d000066400000000000000000000000171360435400500245410ustar00rootroot00000000000000module common; dub-1.19.0/test/issue1350-transitive-none-deps/common-dep/dub.sdl000066400000000000000000000001161360435400500243620ustar00rootroot00000000000000name "common-dep" targetType "library" importPaths "." sourceFiles "common.d" dub-1.19.0/test/issue1350-transitive-none-deps/common-none/000077500000000000000000000000001360435400500232755ustar00rootroot00000000000000dub-1.19.0/test/issue1350-transitive-none-deps/common-none/dub.sdl000066400000000000000000000001221360435400500245460ustar00rootroot00000000000000name "common-none" targetType "none" dependency "common-dep" path="../common-dep" dub-1.19.0/test/issue1350-transitive-none-deps/dep1/000077500000000000000000000000001360435400500217015ustar00rootroot00000000000000dub-1.19.0/test/issue1350-transitive-none-deps/dep1/dep1.d000066400000000000000000000000341360435400500226740ustar00rootroot00000000000000module dep1; import common; dub-1.19.0/test/issue1350-transitive-none-deps/dep1/dub.sdl000066400000000000000000000001401360435400500231520ustar00rootroot00000000000000name "dep1" importPaths "." sourceFiles "dep1.d" dependency "common-none" path="../common-none" dub-1.19.0/test/issue1350-transitive-none-deps/dep2/000077500000000000000000000000001360435400500217025ustar00rootroot00000000000000dub-1.19.0/test/issue1350-transitive-none-deps/dep2/dep2.d000066400000000000000000000000341360435400500226760ustar00rootroot00000000000000module dep2; import common; dub-1.19.0/test/issue1350-transitive-none-deps/dep2/dub.sdl000066400000000000000000000001401360435400500231530ustar00rootroot00000000000000name "dep2" importPaths "." sourceFiles "dep2.d" dependency "common-none" path="../common-none" dub-1.19.0/test/issue1350-transitive-none-deps/dub.sdl000066400000000000000000000001651360435400500223300ustar00rootroot00000000000000name "test" targetType "executable" sourceFiles "test.d" dependency "dep1" path="dep1" dependency "dep2" path="dep2" dub-1.19.0/test/issue1350-transitive-none-deps/test.d000066400000000000000000000000711360435400500221720ustar00rootroot00000000000000module test; import dep1, dep2, common; void main() {} dub-1.19.0/test/issue1396-pre-post-run-commands.sh000077500000000000000000000004721360435400500215200ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue1396-pre-post-run-commands rm -rf .dub rm -rf test.txt "$DUB" if ! grep -c -e "pre-run" test.txt; then die $LINENO 'pre run not executed.' fi if ! grep -c -e "post-run-0" test.txt; then die $LINENO 'post run not executed.' fi dub-1.19.0/test/issue1396-pre-post-run-commands/000077500000000000000000000000001360435400500211565ustar00rootroot00000000000000dub-1.19.0/test/issue1396-pre-post-run-commands/.no_build000066400000000000000000000000001360435400500227400ustar00rootroot00000000000000dub-1.19.0/test/issue1396-pre-post-run-commands/dub.sdl000066400000000000000000000001251360435400500224320ustar00rootroot00000000000000name "test" preRunCommands "echo pre-run >> test.txt" postRunCommands "./post-run.sh"dub-1.19.0/test/issue1396-pre-post-run-commands/post-run.sh000077500000000000000000000000611360435400500233010ustar00rootroot00000000000000echo post-run-$DUB_TARGET_EXIT_STATUS >> test.txtdub-1.19.0/test/issue1396-pre-post-run-commands/source/000077500000000000000000000000001360435400500224565ustar00rootroot00000000000000dub-1.19.0/test/issue1396-pre-post-run-commands/source/app.d000066400000000000000000000000171360435400500234010ustar00rootroot00000000000000void main() {} dub-1.19.0/test/issue1401-file-system-pkg-supplier/000077500000000000000000000000001360435400500216505ustar00rootroot00000000000000dub-1.19.0/test/issue1401-file-system-pkg-supplier/.no_build000066400000000000000000000000001360435400500234320ustar00rootroot00000000000000dub-1.19.0/test/issue1401-file-system-pkg-supplier/fs-json-dubpackage-1.0.7.zip000066400000000000000000000013201360435400500264740ustar00rootroot00000000000000PKMfs-json-dubpackage-1.0.7/PK M9F88!fs-json-dubpackage-1.0.7/dub.json{ "name": "fs-json-dubpackage", "sourcePaths": ["."] }PK!M?c'VX fs-json-dubpackage-1.0.7/hello.d 0 |E.E'~8ZjI[n9™#1F0մn9uXKC_o&j5.8xPK?M$fs-json-dubpackage-1.0.7/ #f#fk6PK? M9F88!$ 7fs-json-dubpackage-1.0.7/dub.json A{77PK?!M?c'VX $ fs-json-dubpackage-1.0.7/hello.d G28787PKPB(9e3972be4c63790c32257220f40c0af7dc41bec5dub-1.19.0/test/issue1401-file-system-pkg-supplier/fs-sdl-dubpackage-1.0.5.zip000066400000000000000000000014201360435400500263040ustar00rootroot00000000000000PKMfs-sdl-dubpackage-1.0.5/PKΦM`Cfs-sdl-dubpackage-1.0.5/dub.sdleA = oD/01]ą}'_ą4Le('fE@OJlu.FP6)xXCh#O*fOo+ 7 ֥KgbN:wƼ5,#PKҦMr VXfs-sdl-dubpackage-1.0.5/hello.d 0 |E.E~8ZjI[n9™#1F0մn9uXKC_o&j5.8xPK?M$fs-sdl-dubpackage-1.0.5/ 8787k6PK?ΦM`C$ 6fs-sdl-dubpackage-1.0.5/dub.sdl T'77PK?ҦMr VX$ fs-sdl-dubpackage-1.0.5/hello.d <-8787PKL(9e3972be4c63790c32257220f40c0af7dc41bec5dub-1.19.0/test/issue1401-file-system-pkg-supplier/fs-sdl-dubpackage-1.0.6.zip000066400000000000000000000014201360435400500263050ustar00rootroot00000000000000PKMfs-sdl-dubpackage-1.0.6/PKæM`Cfs-sdl-dubpackage-1.0.6/dub.sdleA = oD/01]ą}'_ą4Le('fE@OJlu.FP6)xXCh#O*fOo+ 7 ֥KgbN:wƼ5,#PKئMhPVXfs-sdl-dubpackage-1.0.6/hello.d 0 |E.E~8ZjI[n9™#1F0մn9uXKC_o&j5.8xPK?M$fs-sdl-dubpackage-1.0.6/ ԗԗJ_PK?æM`C$ 6fs-sdl-dubpackage-1.0.6/dub.sdl qwwPK?ئMhPVX$ fs-sdl-dubpackage-1.0.6/hello.d ەd3ԗԗPKL(9e3972be4c63790c32257220f40c0af7dc41bec5dub-1.19.0/test/issue1401-filesystem-supplier.sh000077500000000000000000000022511360435400500213530ustar00rootroot00000000000000#!/usr/bin/env bash DIR=$(dirname "${BASH_SOURCE[0]}") . "$DIR"/common.sh dub remove fs-json-dubpackage --non-interactive --version=* 2>/dev/null || true dub remove fs-sdl-dubpackage --non-interactive --version=* 2>/dev/null || true echo "Trying to get fs-sdl-dubpackage (1.0.5)" "$DUB" fetch fs-sdl-dubpackage --version=1.0.5 --skip-registry=all --registry=file://"$DIR"/issue1401-file-system-pkg-supplier if ! dub remove fs-sdl-dubpackage --non-interactive --version=1.0.5 2>/dev/null; then die 'DUB did not install package from file system.' fi echo "Trying to get fs-sdl-dubpackage (latest)" "$DUB" fetch fs-sdl-dubpackage --skip-registry=all --registry=file://"$DIR"/issue1401-file-system-pkg-supplier if ! dub remove fs-sdl-dubpackage --non-interactive --version=1.0.6 2>/dev/null; then die 'DUB did not install latest package from file system.' fi echo "Trying to get fs-json-dubpackage (1.0.7)" "$DUB" fetch fs-json-dubpackage --version=1.0.7 --skip-registry=all --registry=file://"$DIR"/issue1401-file-system-pkg-supplier if ! dub remove fs-json-dubpackage --non-interactive --version=1.0.7 2>/dev/null; then die 'DUB did not install package from file system.' fi dub-1.19.0/test/issue1408-inherit-linker-files/000077500000000000000000000000001360435400500210225ustar00rootroot00000000000000dub-1.19.0/test/issue1408-inherit-linker-files/.no_run000066400000000000000000000000001360435400500223110ustar00rootroot00000000000000dub-1.19.0/test/issue1408-inherit-linker-files/.no_test000066400000000000000000000000001360435400500224640ustar00rootroot00000000000000dub-1.19.0/test/issue1408-inherit-linker-files/dep.d000066400000000000000000000000141360435400500217320ustar00rootroot00000000000000module dep; dub-1.19.0/test/issue1408-inherit-linker-files/dub.sdl000066400000000000000000000005201360435400500222750ustar00rootroot00000000000000name "test" targetType "executable" dependency ":dep" version="*" sourceFiles "main.d" // make lib.d available for import importPaths "." subPackage { name "dep" sourceFiles "dep.d" sourceFiles "lib/liblib.a" platform="posix" sourceFiles "lib/lib.lib" platform="windows" preBuildCommands "dub build --root=\"$PACKAGE_DIR/lib\"" } dub-1.19.0/test/issue1408-inherit-linker-files/lib.d000066400000000000000000000000311360435400500217270ustar00rootroot00000000000000module lib; void foo(); dub-1.19.0/test/issue1408-inherit-linker-files/lib/000077500000000000000000000000001360435400500215705ustar00rootroot00000000000000dub-1.19.0/test/issue1408-inherit-linker-files/lib/dub.sdl000066400000000000000000000000721360435400500230450ustar00rootroot00000000000000name "lib" targetType "staticLibrary" sourceFiles "lib.d" dub-1.19.0/test/issue1408-inherit-linker-files/lib/lib.d000066400000000000000000000000341360435400500225000ustar00rootroot00000000000000module lib; void foo() { } dub-1.19.0/test/issue1408-inherit-linker-files/main.d000066400000000000000000000000451360435400500221120ustar00rootroot00000000000000import lib; void main() { foo(); } dub-1.19.0/test/issue1416-maven-repo-pkg-supplier.sh000077500000000000000000000023251360435400500220270ustar00rootroot00000000000000#!/usr/bin/env bash DIR=$(dirname "${BASH_SOURCE[0]}") . "$DIR"/common.sh PORT=$(($$ + 1024)) # PID + 1024 dub remove maven-dubpackage --non-interactive --version=* 2>/dev/null || true "$DUB" build --single "$DIR"/test_registry.d "$DIR"/test_registry --folder="$DIR/issue1416-maven-repo-pkg-supplier" --port=$PORT & PID=$! sleep 1 trap 'kill $PID 2>/dev/null || true' exit echo "Trying to download maven-dubpackage (1.0.5)" "$DUB" fetch maven-dubpackage --version=1.0.5 --skip-registry=all --registry=mvn+http://localhost:$PORT/maven/release/dubpackages if ! dub remove maven-dubpackage --non-interactive --version=1.0.5 2>/dev/null; then die 'DUB did not install package from maven registry.' fi echo "Trying to download maven-dubpackage (latest)" "$DUB" fetch maven-dubpackage --skip-registry=all --registry=mvn+http://localhost:$PORT/maven/release/dubpackages if ! dub remove maven-dubpackage --non-interactive --version=1.0.6 2>/dev/null; then die 'DUB fetch did not install latest package from maven registry.' fi echo "Trying to search (exact) maven-dubpackage" "$DUB" search maven-dubpackage --skip-registry=all --registry=mvn+http://localhost:$PORT/maven/release/dubpackages | grep -c "maven-dubpackage (1.0.6)" dub-1.19.0/test/issue1416-maven-repo-pkg-supplier.sh.min_frontend000066400000000000000000000000061360435400500244770ustar00rootroot000000000000002.076 dub-1.19.0/test/issue1416-maven-repo-pkg-supplier/000077500000000000000000000000001360435400500214665ustar00rootroot00000000000000dub-1.19.0/test/issue1416-maven-repo-pkg-supplier/.gitignore000066400000000000000000000000701360435400500234530ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ *.exe *.o *.obj *.lst dub-1.19.0/test/issue1416-maven-repo-pkg-supplier/.no_build000066400000000000000000000000001360435400500232500ustar00rootroot00000000000000dub-1.19.0/test/issue1416-maven-repo-pkg-supplier/maven/000077500000000000000000000000001360435400500225745ustar00rootroot00000000000000dub-1.19.0/test/issue1416-maven-repo-pkg-supplier/maven/release/000077500000000000000000000000001360435400500242145ustar00rootroot00000000000000dub-1.19.0/test/issue1416-maven-repo-pkg-supplier/maven/release/dubpackages/000077500000000000000000000000001360435400500264655ustar00rootroot00000000000000dub-1.19.0/test/issue1416-maven-repo-pkg-supplier/maven/release/dubpackages/maven-dubpackage/000077500000000000000000000000001360435400500316575ustar00rootroot00000000000000dub-1.19.0/test/issue1416-maven-repo-pkg-supplier/maven/release/dubpackages/maven-dubpackage/1.0.5/000077500000000000000000000000001360435400500323205ustar00rootroot00000000000000maven-dubpackage-1.0.5.zip000066400000000000000000000014161360435400500366200ustar00rootroot00000000000000dub-1.19.0/test/issue1416-maven-repo-pkg-supplier/maven/release/dubpackages/maven-dubpackage/1.0.5PKKwLmaven-dubpackage-1.0.5/PKRwLHmaven-dubpackage-1.0.5/dub.sdleA = pm``LE\[?FN,ho TR,Ut ^ Z C龆Sl JC]x!t Lyr ]lV}CPKR2K[\maven-dubpackage-1.0.5/hello.d; 0=b4^ Xx+$ą|dj!kfRqWx 9L”öP5m‚UNa^ymPK?KwL$maven-dubpackage-1.0.5/ VjVj}iPK?RwLH$ 5maven-dubpackage-1.0.5/dub.sdl O5+i+iPK?R2K[\$ maven-dubpackage-1.0.5/hello.d ~0VjVjPKI(9e3972be4c63790c32257220f40c0af7dc41bec5dub-1.19.0/test/issue1416-maven-repo-pkg-supplier/maven/release/dubpackages/maven-dubpackage/1.0.6/000077500000000000000000000000001360435400500323215ustar00rootroot00000000000000maven-dubpackage-1.0.6.zip000066400000000000000000000014161360435400500366220ustar00rootroot00000000000000dub-1.19.0/test/issue1416-maven-repo-pkg-supplier/maven/release/dubpackages/maven-dubpackage/1.0.6PK@TxLmaven-dubpackage-1.0.6/PKRwLHmaven-dubpackage-1.0.6/dub.sdleA = pm``LE\[?FN,ho TR,Ut ^ Z C龆Sl JC]x!t Lyr ]lV}CPKR2K[\maven-dubpackage-1.0.6/hello.d; 0=b4^ Xx+$ą|dj!kfRqWx 9L”öP5m‚UNa^ymPK?@TxL$maven-dubpackage-1.0.6/ =S=S3=SPK?RwLH$ 5maven-dubpackage-1.0.6/dub.sdl O5 [=S [=SPK?R2K[\$ maven-dubpackage-1.0.6/hello.d ~0=S=SPKI(9e3972be4c63790c32257220f40c0af7dc41bec5maven-metadata.xml000066400000000000000000000006011360435400500352030ustar00rootroot00000000000000dub-1.19.0/test/issue1416-maven-repo-pkg-supplier/maven/release/dubpackages/maven-dubpackage dubpackages maven-dubpackage 1.0.6 1.0.6 1.0.5 1.0.6 20180317184845 dub-1.19.0/test/issue1427-betterC/000077500000000000000000000000001360435400500163675ustar00rootroot00000000000000dub-1.19.0/test/issue1427-betterC/.gitignore000066400000000000000000000000231360435400500203520ustar00rootroot00000000000000test *.o *.exe .dubdub-1.19.0/test/issue1427-betterC/.min_frontend000066400000000000000000000000061360435400500210460ustar00rootroot000000000000002.078 dub-1.19.0/test/issue1427-betterC/.no_run000066400000000000000000000000001360435400500176560ustar00rootroot00000000000000dub-1.19.0/test/issue1427-betterC/.no_test000066400000000000000000000000001360435400500200310ustar00rootroot00000000000000dub-1.19.0/test/issue1427-betterC/dub.json000066400000000000000000000000611360435400500200310ustar00rootroot00000000000000{ "name": "test", "buildOptions": ["betterC"] }dub-1.19.0/test/issue1427-betterC/source/000077500000000000000000000000001360435400500176675ustar00rootroot00000000000000dub-1.19.0/test/issue1427-betterC/source/app.d000066400000000000000000000001131360435400500206070ustar00rootroot00000000000000version(D_BetterC) {} else static assert(false); extern(C) void main() { }dub-1.19.0/test/issue1447-build-settings-vars.sh000077500000000000000000000011021360435400500212400ustar00rootroot00000000000000#!/usr/bin/env bash set -e . $(dirname "${BASH_SOURCE[0]}")/common.sh if [[ `uname -m` == "x86_64" ]]; then ARCH=x86_64 else ARCH=x86 fi rm -rf ${CURR_DIR}/issue1447-build-settings-vars/.dub rm -rf ${CURR_DIR}/issue1447-build-settings-vars/test ${DUB} build --root ${CURR_DIR}/issue1447-build-settings-vars --arch=$ARCH OUTPUT=`${CURR_DIR}/issue1447-build-settings-vars/test` rm -rf ${CURR_DIR}/issue1447-build-settings-vars/.dub rm -rf ${CURR_DIR}/issue1447-build-settings-vars/test if [[ "$OUTPUT" != "$ARCH" ]]; then die "Build settings ARCH var incorrect"; fi dub-1.19.0/test/issue1447-build-settings-vars/000077500000000000000000000000001360435400500207075ustar00rootroot00000000000000dub-1.19.0/test/issue1447-build-settings-vars/.no_run000066400000000000000000000000001360435400500221760ustar00rootroot00000000000000dub-1.19.0/test/issue1447-build-settings-vars/.no_test000066400000000000000000000000001360435400500223510ustar00rootroot00000000000000dub-1.19.0/test/issue1447-build-settings-vars/dub.json000066400000000000000000000000711360435400500223520ustar00rootroot00000000000000{ "name": "test", "stringImportPaths": ["view-$ARCH"] }dub-1.19.0/test/issue1447-build-settings-vars/source/000077500000000000000000000000001360435400500222075ustar00rootroot00000000000000dub-1.19.0/test/issue1447-build-settings-vars/source/app.d000066400000000000000000000000751360435400500231360ustar00rootroot00000000000000import std.stdio; void main() { writeln(import("arch")); } dub-1.19.0/test/issue1447-build-settings-vars/view-x86/000077500000000000000000000000001360435400500223045ustar00rootroot00000000000000dub-1.19.0/test/issue1447-build-settings-vars/view-x86/arch000066400000000000000000000000031360435400500231350ustar00rootroot00000000000000x86dub-1.19.0/test/issue1447-build-settings-vars/view-x86_64/000077500000000000000000000000001360435400500226155ustar00rootroot00000000000000dub-1.19.0/test/issue1447-build-settings-vars/view-x86_64/arch000066400000000000000000000000061360435400500234510ustar00rootroot00000000000000x86_64dub-1.19.0/test/issue1504-envvar-in-path.sh000077500000000000000000000010061360435400500201660ustar00rootroot00000000000000#!/usr/bin/env bash set -e . $(dirname "${BASH_SOURCE[0]}")/common.sh rm -rf ${CURR_DIR}/issue1504-envvar-in-path/.dub rm -rf ${CURR_DIR}/issue1504-envvar-in-path/test rm -rf ${CURR_DIR}/output-1504.txt export MY_VARIABLE=teststrings # pragma(msg) outputs to stderr ${DUB} build --force --root ${CURR_DIR}/issue1504-envvar-in-path 2> ${CURR_DIR}/output-1504.txt grep "env_variables_work" < ${CURR_DIR}/output-1504.txt # Don't manage to make it work #grep "Invalid source" < ${CURR_DIR}/output-1504.txt && true dub-1.19.0/test/issue1504-envvar-in-path/000077500000000000000000000000001360435400500176325ustar00rootroot00000000000000dub-1.19.0/test/issue1504-envvar-in-path/.no_build000066400000000000000000000000001360435400500214140ustar00rootroot00000000000000dub-1.19.0/test/issue1504-envvar-in-path/dub.json000066400000000000000000000001031360435400500212710ustar00rootroot00000000000000{ "name": "test", "stringImportPaths": ["$MY_VARIABLE"] } dub-1.19.0/test/issue1504-envvar-in-path/source/000077500000000000000000000000001360435400500211325ustar00rootroot00000000000000dub-1.19.0/test/issue1504-envvar-in-path/source/app.d000066400000000000000000000000701360435400500220540ustar00rootroot00000000000000pragma(msg, import("message.txt")); void main() { }dub-1.19.0/test/issue1504-envvar-in-path/teststrings/000077500000000000000000000000001360435400500222235ustar00rootroot00000000000000dub-1.19.0/test/issue1504-envvar-in-path/teststrings/message.txt000066400000000000000000000000221360435400500244020ustar00rootroot00000000000000env_variables_workdub-1.19.0/test/issue1524-maven-upgrade-dependency-tree.sh000077500000000000000000000020521360435400500231370ustar00rootroot00000000000000#!/usr/bin/env bash DIR=$(dirname "${BASH_SOURCE[0]}") . "$DIR"/common.sh PORT=$(($$ + 1024)) # PID + 1024 dub remove maven-dubpackage-a --non-interactive --version=* 2>/dev/null || true dub remove maven-dubpackage-b --non-interactive --version=* 2>/dev/null || true "$DUB" build --single "$DIR"/test_registry.d "$DIR"/test_registry --folder="$DIR/issue1524-maven-upgrade-dependency-tree" --port=$PORT & PID=$! sleep 1 trap 'kill $PID 2>/dev/null || true' exit echo "Trying to download maven-dubpackage-a (1.0.5) with dependency to maven-dubpackage-b (1.0.6)" "$DUB" upgrade --root "$DIR/issue1524-maven-upgrade-dependency-tree" --skip-registry=standard --registry=mvn+http://localhost:$PORT/maven/release/dubpackages if ! dub remove maven-dubpackage-a --non-interactive --version=1.0.5 2>/dev/null; then die 'DUB did not install package "maven-dubpackage-a" from maven registry.' fi if ! dub remove maven-dubpackage-b --non-interactive --version=1.0.6 2>/dev/null; then die 'DUB did not install package "maven-dubpackage-b" from maven registry.' fi dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree.sh.min_frontend000066400000000000000000000000061360435400500256120ustar00rootroot000000000000002.076 dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/000077500000000000000000000000001360435400500226015ustar00rootroot00000000000000dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/.gitignore000066400000000000000000000000701360435400500245660ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ *.exe *.o *.obj *.lst dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/.no_build000066400000000000000000000000001360435400500243630ustar00rootroot00000000000000dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/dub.json000066400000000000000000000001141360435400500242420ustar00rootroot00000000000000{ "name": "test", "dependencies": { "maven-dubpackage-a": "~>1.0.5" } }dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/maven/000077500000000000000000000000001360435400500237075ustar00rootroot00000000000000dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/maven/release/000077500000000000000000000000001360435400500253275ustar00rootroot00000000000000dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/maven/release/dubpackages/000077500000000000000000000000001360435400500276005ustar00rootroot00000000000000maven-dubpackage-a/000077500000000000000000000000001360435400500331315ustar00rootroot00000000000000dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/maven/release/dubpackages1.0.5/000077500000000000000000000000001360435400500335725ustar00rootroot00000000000000dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/maven/release/dubpackages/maven-dubpackage-amaven-dubpackage-a-1.0.5.zip000066400000000000000000000014661360435400500403740ustar00rootroot00000000000000dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/maven/release/dubpackages/maven-dubpackage-a/1.0.5PKMmaven-dubpackage-a-1.0.5/PKM9bӍ maven-dubpackage-a-1.0.5/dub.sdlm;0ާ'Jj$ ǎ!8;)-g$ dubpackages maven-dubpackage-a 1.0.5 1.0.5 1.0.5 20180317184845 maven-dubpackage-b/000077500000000000000000000000001360435400500331325ustar00rootroot00000000000000dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/maven/release/dubpackages1.0.6/000077500000000000000000000000001360435400500335745ustar00rootroot00000000000000dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/maven/release/dubpackages/maven-dubpackage-bmaven-dubpackage-b-1.0.6.zip000066400000000000000000000014331360435400500403720ustar00rootroot00000000000000dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/maven/release/dubpackages/maven-dubpackage-b/1.0.6PKMmaven-dubpackage-b-1.0.6/PKȤME|" maven-dubpackage-b-1.0.6/dub.sdleK 0yV]cA7pMRq8?C-\i$eSe>EMXAyBn m[e#xgёzw}4V|PKR2K[\ maven-dubpackage-b-1.0.6/hello.d; 0=b4^ Xx+$ą|dj!kfRqWx 9L”öP5m‚UNa^ymPK?M$maven-dubpackage-b-1.0.6/ &o4&o4n4PK?ȤME|" $ 7maven-dubpackage-b-1.0.6/dub.sdl )!4n4n4PK?R2K[\ $ maven-dubpackage-b-1.0.6/hello.d ~0&o4&o4PKO(9e3972be4c63790c32257220f40c0af7dc41bec5maven-metadata.xml000066400000000000000000000005441360435400500365430ustar00rootroot00000000000000dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/maven/release/dubpackages/maven-dubpackage-b dubpackages maven-dubpackage-b 1.0.6 1.0.6 1.0.6 20180317184845 dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/source/000077500000000000000000000000001360435400500241015ustar00rootroot00000000000000dub-1.19.0/test/issue1524-maven-upgrade-dependency-tree/source/app.d000066400000000000000000000000151360435400500250220ustar00rootroot00000000000000void main(){}dub-1.19.0/test/issue1531-toolchain-requirements.sh000077500000000000000000000046121360435400500220360ustar00rootroot00000000000000#!/usr/bin/env bash set -e . $(dirname "${BASH_SOURCE[0]}")/common.sh cat << EOF | $DUB - || die "Did not pass without toolchainRequirements" /+ dub.sdl: +/ void main() {} EOF # pass test dub requirement given as $1 function test_dub_req_pass { cat << EOF | $DUB - || die "Did not pass requirement dub=\"$1\"" /+ dub.sdl: toolchainRequirements dub="$1" +/ void main() {} EOF } # fail test dub requirement given as $1 function test_dub_req_fail { ! cat << EOF | $DUB - || die "Did not pass requirement dub=\"$1\"" /+ dub.sdl: toolchainRequirements dub="$1" +/ void main() {} EOF } test_dub_req_pass ">=1.7.0" test_dub_req_fail "~>0.9" test_dub_req_fail "~>999.0" # extract compiler version if [[ $DC == *ldc* ]] || [[ $DC == *ldmd* ]]; then VER_REG='\((([[:digit:]]+)(\.[[:digit:]]+\.[[:digit:]]+[A-Za-z0-9.+-]*))\)' DC_NAME=ldc elif [[ $DC == *dmd* ]]; then VER_REG='v(([[:digit:]]+)(\.[[:digit:]]+\.[[:digit:]]+[A-Za-z0-9.+-]*))' DC_NAME=dmd elif [[ $DC == *gdc* ]]; then VER_REG='\) (([[:digit:]]+)(\.[[:digit:]]+\.[[:digit:]]+[A-Za-z0-9.+-]*))' DC_NAME=gdc else die "Did not recognize compiler" fi if [[ $($DC --version) =~ $VER_REG ]]; then DC_VER=${BASH_REMATCH[1]} DC_VER_MAJ=${BASH_REMATCH[2]} DC_VER_REM=${BASH_REMATCH[3]} $DC --version echo $DC version is $DC_VER else $DC --version die "Could not extract compiler version" fi # create test app directory TMPDIR=$(mktemp -d /tmp/dubtest1531_XXXXXX) mkdir -p $TMPDIR/source cat << EOF > $TMPDIR/source/app.d module dubtest1531; void main() {} EOF # write dub.sdl with compiler requirement given as $1 function write_cl_req { cat << EOF > $TMPDIR/dub.sdl name "dubtest1531" toolchainRequirements ${DC_NAME}="$1" EOF } # pass test compiler requirement given as $1 function test_cl_req_pass { write_cl_req $1 $DUB --compiler=$DC --root=$TMPDIR || die "Did not pass with $DC_NAME=\"$1\"" } # fail test compiler requirement given as $1 function test_cl_req_fail { write_cl_req $1 ! $DUB --compiler=$DC --root=$TMPDIR || die "Did not fail with $DC_NAME=\"$1\"" } test_cl_req_pass "==$DC_VER" test_cl_req_pass ">=$DC_VER" test_cl_req_fail ">$DC_VER" test_cl_req_pass "<=$DC_VER" test_cl_req_fail "<$DC_VER" test_cl_req_pass ">=$DC_VER <$(($DC_VER_MAJ + 1))$DC_VER_REM" test_cl_req_pass "~>$DC_VER" test_cl_req_fail "~>$(($DC_VER_MAJ + 1))$DC_VER_REM" test_cl_req_fail no rm -rf $TMPDIR dub-1.19.0/test/issue1551-var-escaping/000077500000000000000000000000001360435400500173545ustar00rootroot00000000000000dub-1.19.0/test/issue1551-var-escaping/dub.json000066400000000000000000000002171360435400500210210ustar00rootroot00000000000000{ "name": "issue1551-var-escaping", "preGenerateCommands": [ "echo $${DUB_PACKAGE_DIR}", "echo $$DUB_PACKAGE_DIR" ] } dub-1.19.0/test/issue1551-var-escaping/source/000077500000000000000000000000001360435400500206545ustar00rootroot00000000000000dub-1.19.0/test/issue1551-var-escaping/source/app.d000066400000000000000000000001311360435400500215740ustar00rootroot00000000000000import std.stdio; void main() { writeln("Edit source/app.d to start your project."); } dub-1.19.0/test/issue1567-fetch-sub-package.sh000077500000000000000000000007701360435400500206200ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh DIR=$(dirname "${BASH_SOURCE[0]}") packname="fetch-sub-package-dubpackage" sub_packagename="my-sub-package" $DUB remove $packname --non-interactive --version=* 2>/dev/null || true $DUB fetch "$packname:$sub_packagename" --skip-registry=all --registry=file://"$DIR"/issue1567-fetch-sub-package if ! dub remove $packname --non-interactive --version=1.0.1 2>/dev/null; then die 'DUB did not install package $packname:$sub_packagename.' fidub-1.19.0/test/issue1567-fetch-sub-package/000077500000000000000000000000001360435400500202555ustar00rootroot00000000000000dub-1.19.0/test/issue1567-fetch-sub-package/.no_build000066400000000000000000000000001360435400500220370ustar00rootroot00000000000000dub-1.19.0/test/issue1567-fetch-sub-package/.no_run000066400000000000000000000000001360435400500215440ustar00rootroot00000000000000dub-1.19.0/test/issue1567-fetch-sub-package/.no_test000066400000000000000000000000001360435400500217170ustar00rootroot00000000000000dub-1.19.0/test/issue1567-fetch-sub-package/fetch-sub-package-dubpackage-1.0.1.zip000066400000000000000000000037101360435400500267720ustar00rootroot00000000000000PKjN#fetch-sub-package-dubpackage-1.0.1/PKjN~Ca+fetch-sub-package-dubpackage-1.0.1/dub.json]̽ Y{3FUG?B!{O!snF 8iD z!*>DЕAΠ;,& AS Jrkb~gFPKәjN2fetch-sub-package-dubpackage-1.0.1/my-sub-package/PK jN$Z;==:fetch-sub-package-dubpackage-1.0.1/my-sub-package/dub.json{ "name": "my-sub-package", "targetType": "executable" }PKәjN9fetch-sub-package-dubpackage-1.0.1/my-sub-package/source/PK jNf`0LL>fetch-sub-package-dubpackage-1.0.1/my-sub-package/source/app.dimport std.stdio: writeln; void main() { writeln("my-sub-package"); }PKәjN*fetch-sub-package-dubpackage-1.0.1/source/PK jNN2ٝ44/fetch-sub-package-dubpackage-1.0.1/source/app.dvoid main() { assert(false, "Should not run"); }PK?jN#$fetch-sub-package-dubpackage-1.0.1/ UBmUBmPGmPK?jN~Ca+$ Afetch-sub-package-dubpackage-1.0.1/dub.json ik =m@Gm@GmPK?әjN2$fetch-sub-package-dubpackage-1.0.1/my-sub-package/ HmHmqGmPK? jN$Z;==:$ ;fetch-sub-package-dubpackage-1.0.1/my-sub-package/dub.json GIm:Hm:HmPK?әjN9$fetch-sub-package-dubpackage-1.0.1/my-sub-package/source/ HmHmHmPK? jNf`0LL>$ 'fetch-sub-package-dubpackage-1.0.1/my-sub-package/source/app.d w_mHmHmPK?әjN*$fetch-sub-package-dubpackage-1.0.1/source/ sImsIm$ImPK? jNN2ٝ44/$ fetch-sub-package-dubpackage-1.0.1/source/app.d (sImsImPKdub-1.19.0/test/issue1574-addcommand.sh000077500000000000000000000021511360435400500174270ustar00rootroot00000000000000#!/usr/bin/env bash DIR=$(dirname "${BASH_SOURCE[0]}") . "$DIR"/common.sh PORT=$(($$ + 1024)) # PID + 1024 tempDir="issue1574-addcommand" "$DUB" build --single "$DIR"/test_registry.d "$DIR"/test_registry --folder="$DIR/issue1336-registry" --port=$PORT & PID=$! sleep 1 function cleanup { cd .. rm -rf $tempDir kill $PID 2>/dev/null || true } trap cleanup EXIT $DUB init --non-interactive --format=json $tempDir cd $tempDir echo "import gitcompatibledubpackage.subdir.file; void main(){}" > source/app.d $DUB add gitcompatibledubpackage --skip-registry=all --registry=http://localhost:$PORT grep -q '"gitcompatibledubpackage"\s*:\s*"~>1\.0\.4"' dub.json $DUB add gitcompatibledubpackage=1.0.2 non-existing-issue1574-pkg='~>9.8.7' --skip-registry=all grep -q '"gitcompatibledubpackage"\s*:\s*"1\.0\.2"' dub.json grep -q '"non-existing-issue1574-pkg"\s*:\s*"~>9\.8\.7"' dub.json if $DUB add foo@1.2.3 gitcompatibledubpackage='~>a.b.c' --skip-registry=all; then die $LINENO 'Adding non-semver spec should error' fi if grep -q '"foo"' dub.json; then die $LINENO 'Failing add command should not write recipe file' fi dub-1.19.0/test/issue1574-addcommand.sh.min_frontend000066400000000000000000000000061360435400500221020ustar00rootroot000000000000002.076 dub-1.19.0/test/issue1651-custom-dub-init-type.sh000077500000000000000000000012471360435400500213430ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh DIR=$(dirname "${BASH_SOURCE[0]}") packname="custom-dub-init-type-sample" $DUB remove custom-dub-init-dubpackage --non-interactive --version=* 2>/dev/null || true $DUB init -n $packname --format sdl -t custom-dub-init-dubpackage --skip-registry=all --registry=file://"$DIR"/issue1651-custom-dub-init-type -- --foo=bar function cleanup { rm -rf $packname } if [ ! -e $packname/dub.sdl ]; then # it failed cleanup die $LINENO 'No dub.sdl file has been generated.' fi cd $packname if ! { ${DUB} 2>&1 || true; } | grep -cF 'foo=bar'; then cd .. cleanup die $LINENO 'Custom init type.' fi cd .. cleanupdub-1.19.0/test/issue1651-custom-dub-init-type/000077500000000000000000000000001360435400500210005ustar00rootroot00000000000000dub-1.19.0/test/issue1651-custom-dub-init-type/.no_build000066400000000000000000000000001360435400500225620ustar00rootroot00000000000000dub-1.19.0/test/issue1651-custom-dub-init-type/.no_run000066400000000000000000000000001360435400500222670ustar00rootroot00000000000000dub-1.19.0/test/issue1651-custom-dub-init-type/.no_test000066400000000000000000000000001360435400500224420ustar00rootroot00000000000000dub-1.19.0/test/issue1651-custom-dub-init-type/custom-dub-init-dubpackage-1.0.1.zip000066400000000000000000000040471360435400500272730ustar00rootroot00000000000000PKofjN!custom-dub-init-dubpackage-1.0.1/PK iN$a{)custom-dub-init-dubpackage-1.0.1/dub.jsonEM uwh-y&wOߦ0|3/g|{a.CTR'ܝňb0S};$~1A++TFk;,/PKofjN+custom-dub-init-dubpackage-1.0.1/init-exec/PK sfjN~8883custom-dub-init-dubpackage-1.0.1/init-exec/dub.json{ "name": "init-exec", "targetType": "executable" }PKofjN2custom-dub-init-dubpackage-1.0.1/init-exec/source/PKYNBħ7custom-dub-init-dubpackage-1.0.1/init-exec/source/app.d]Pj0 =/6î ݱv/xjKl+t^9.ۃ@H===aAm[ @jɡ4ݏ =켗 |[4(_Ph<~ũ, &{;V=0^C0o6[c9k/ҹ5=5r; iL(goh4bye+g&a]?H*금oNsR,;]C%CIy%~,=wQ|PKofjN(custom-dub-init-dubpackage-1.0.1/source/PK jNN2ٝ44-custom-dub-init-dubpackage-1.0.1/source/app.dvoid main() { assert(false, "Should not run"); }PK?ofjN!$custom-dub-init-dubpackage-1.0.1/ 77*7PK? iN$a{)$ ?custom-dub-init-dubpackage-1.0.1/dub.json X;7X;7PK?ofjN+$custom-dub-init-dubpackage-1.0.1/init-exec/ %7%7v7PK? sfjN~8883$ 0custom-dub-init-dubpackage-1.0.1/init-exec/dub.json e1777PK?ofjN2$custom-dub-init-dubpackage-1.0.1/init-exec/source/ s7s7%7PK?YNBħ7$ custom-dub-init-dubpackage-1.0.1/init-exec/source/app.d (Cs7s7PK?ofjN($Vcustom-dub-init-dubpackage-1.0.1/source/ >^7>^77PK? jNN2ٝ44-$ custom-dub-init-dubpackage-1.0.1/source/app.d (>^7>^7PKdub-1.19.0/test/issue1691-build-subpkg.sh000077500000000000000000000001741360435400500177330ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh $DUB build --root="$CURR_DIR/issue1691-build-subpkg" :subpkg dub-1.19.0/test/issue1691-build-subpkg/000077500000000000000000000000001360435400500173725ustar00rootroot00000000000000dub-1.19.0/test/issue1691-build-subpkg/.gitignore000066400000000000000000000003641360435400500213650ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ /issue1691-build-subpkg issue1691-build-subpkg.so issue1691-build-subpkg.dylib issue1691-build-subpkg.dll issue1691-build-subpkg.a issue1691-build-subpkg.lib issue1691-build-subpkg-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/issue1691-build-subpkg/.no_build000066400000000000000000000000001360435400500211540ustar00rootroot00000000000000dub-1.19.0/test/issue1691-build-subpkg/dub.sdl000066400000000000000000000001261360435400500206470ustar00rootroot00000000000000name "issue1691-build-subpkg" dependency ":subpkg" version="*" subPackage "./subpkg/" dub-1.19.0/test/issue1691-build-subpkg/source/000077500000000000000000000000001360435400500206725ustar00rootroot00000000000000dub-1.19.0/test/issue1691-build-subpkg/source/app.d000066400000000000000000000000001360435400500216050ustar00rootroot00000000000000dub-1.19.0/test/issue1691-build-subpkg/subpkg/000077500000000000000000000000001360435400500206655ustar00rootroot00000000000000dub-1.19.0/test/issue1691-build-subpkg/subpkg/dub.sdl000066400000000000000000000000161360435400500221400ustar00rootroot00000000000000name "subpkg" dub-1.19.0/test/issue1691-build-subpkg/subpkg/source/000077500000000000000000000000001360435400500221655ustar00rootroot00000000000000dub-1.19.0/test/issue1691-build-subpkg/subpkg/source/subpkg.d000066400000000000000000000000001360435400500236130ustar00rootroot00000000000000dub-1.19.0/test/issue1739-project-settings-file.sh000077500000000000000000000006641360435400500215730ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR} echo "{\"defaultArchitecture\": \"foo\"}" > "dub.settings.json" function cleanup { rm "dub.settings.json" } trap cleanup EXIT if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "Unsupported architecture: foo"; then die $LINENO 'DUB did not find the project configuration with an adjacent architecture.' fi dub-1.19.0/test/issue1773-lint.sh000077500000000000000000000004151360435400500163100ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh DIR=$(dirname "${BASH_SOURCE[0]}") if ! { ${DUB} lint --root ${DIR}/issue1773-lint || true; } | grep -cF "Parameter args is never used."; then die $LINENO 'DUB lint did not find expected warning.' fi dub-1.19.0/test/issue1773-lint/000077500000000000000000000000001360435400500157515ustar00rootroot00000000000000dub-1.19.0/test/issue1773-lint/.gitignore000066400000000000000000000000701360435400500177360ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ *.exe *.o *.obj *.lst dub-1.19.0/test/issue1773-lint/.no_build000066400000000000000000000000001360435400500175330ustar00rootroot00000000000000dub-1.19.0/test/issue1773-lint/dub.json000066400000000000000000000000231360435400500174110ustar00rootroot00000000000000{ "name": "test" }dub-1.19.0/test/issue1773-lint/source/000077500000000000000000000000001360435400500172515ustar00rootroot00000000000000dub-1.19.0/test/issue1773-lint/source/app.d000066400000000000000000000000351360435400500201740ustar00rootroot00000000000000void main(string[] args) { }dub-1.19.0/test/issue1775/000077500000000000000000000000001360435400500150075ustar00rootroot00000000000000dub-1.19.0/test/issue1775/.no_run000066400000000000000000000000001360435400500162760ustar00rootroot00000000000000dub-1.19.0/test/issue1775/.no_test000066400000000000000000000000001360435400500164510ustar00rootroot00000000000000dub-1.19.0/test/issue1775/dub.json000066400000000000000000000001641360435400500164550ustar00rootroot00000000000000{ "name": "test", "targetName": "test-application", "preBuildCommands": [ "[ -f issue1775.marker ]" ] } dub-1.19.0/test/issue1775/issue1775.marker000066400000000000000000000000001360435400500176540ustar00rootroot00000000000000dub-1.19.0/test/issue1775/source/000077500000000000000000000000001360435400500163075ustar00rootroot00000000000000dub-1.19.0/test/issue1775/source/app.d000066400000000000000000000000171360435400500172320ustar00rootroot00000000000000void main() {} dub-1.19.0/test/issue1788-incomplete-string-import-override/000077500000000000000000000000001360435400500236015ustar00rootroot00000000000000dub-1.19.0/test/issue1788-incomplete-string-import-override/b/000077500000000000000000000000001360435400500240225ustar00rootroot00000000000000dub-1.19.0/test/issue1788-incomplete-string-import-override/b/dub.sdl000066400000000000000000000000111360435400500252700ustar00rootroot00000000000000name "b" dub-1.19.0/test/issue1788-incomplete-string-import-override/b/source/000077500000000000000000000000001360435400500253225ustar00rootroot00000000000000dub-1.19.0/test/issue1788-incomplete-string-import-override/b/source/b/000077500000000000000000000000001360435400500255435ustar00rootroot00000000000000dub-1.19.0/test/issue1788-incomplete-string-import-override/b/source/b/foo.d000066400000000000000000000002321360435400500264700ustar00rootroot00000000000000module b.foo; string bar() { static immutable l = import("layout.diet"); pragma(msg, l); static assert(l == "fancylayout.diet"); return import(l); } dub-1.19.0/test/issue1788-incomplete-string-import-override/b/views/000077500000000000000000000000001360435400500251575ustar00rootroot00000000000000dub-1.19.0/test/issue1788-incomplete-string-import-override/b/views/layout.diet000066400000000000000000000000111360435400500273330ustar00rootroot00000000000000not fancydub-1.19.0/test/issue1788-incomplete-string-import-override/c/000077500000000000000000000000001360435400500240235ustar00rootroot00000000000000dub-1.19.0/test/issue1788-incomplete-string-import-override/c/dub.sdl000066400000000000000000000000111360435400500252710ustar00rootroot00000000000000name "c" dub-1.19.0/test/issue1788-incomplete-string-import-override/c/source/000077500000000000000000000000001360435400500253235ustar00rootroot00000000000000dub-1.19.0/test/issue1788-incomplete-string-import-override/c/source/dummy.d000066400000000000000000000000001360435400500266110ustar00rootroot00000000000000dub-1.19.0/test/issue1788-incomplete-string-import-override/c/views/000077500000000000000000000000001360435400500251605ustar00rootroot00000000000000dub-1.19.0/test/issue1788-incomplete-string-import-override/c/views/fancylayout.diet000066400000000000000000000000051360435400500303600ustar00rootroot00000000000000fancydub-1.19.0/test/issue1788-incomplete-string-import-override/dub.sdl000066400000000000000000000000721360435400500250560ustar00rootroot00000000000000name "a" dependency "b" path="b" dependency "c" path="c" dub-1.19.0/test/issue1788-incomplete-string-import-override/source/000077500000000000000000000000001360435400500251015ustar00rootroot00000000000000dub-1.19.0/test/issue1788-incomplete-string-import-override/source/app.d000066400000000000000000000001671360435400500260320ustar00rootroot00000000000000import b.foo; void main() { static assert(import("layout.diet") == "fancylayout.diet"); assert(bar() == "fancy"); } dub-1.19.0/test/issue1788-incomplete-string-import-override/views/000077500000000000000000000000001360435400500247365ustar00rootroot00000000000000dub-1.19.0/test/issue1788-incomplete-string-import-override/views/layout.diet000066400000000000000000000000201360435400500271120ustar00rootroot00000000000000fancylayout.dietdub-1.19.0/test/issue346-redundant-flags.sh000077500000000000000000000003141360435400500203310ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue346-redundant-flags ${DUB} build --bare --force --compiler=${DC} -a x86_64 -v main 2>&1 | { ! grep -e '-m64 -m64' -c; } dub-1.19.0/test/issue346-redundant-flags/000077500000000000000000000000001360435400500177745ustar00rootroot00000000000000dub-1.19.0/test/issue346-redundant-flags/.no_build000066400000000000000000000000001360435400500215560ustar00rootroot00000000000000dub-1.19.0/test/issue346-redundant-flags/.no_run000066400000000000000000000000001360435400500212630ustar00rootroot00000000000000dub-1.19.0/test/issue346-redundant-flags/.no_test000066400000000000000000000000001360435400500214360ustar00rootroot00000000000000dub-1.19.0/test/issue346-redundant-flags/a/000077500000000000000000000000001360435400500202145ustar00rootroot00000000000000dub-1.19.0/test/issue346-redundant-flags/a/dub.json000066400000000000000000000000201360435400500216510ustar00rootroot00000000000000{ "name": "a" }dub-1.19.0/test/issue346-redundant-flags/a/source/000077500000000000000000000000001360435400500215145ustar00rootroot00000000000000dub-1.19.0/test/issue346-redundant-flags/a/source/a.d000066400000000000000000000000331360435400500220750ustar00rootroot00000000000000module a; void afun() { } dub-1.19.0/test/issue346-redundant-flags/b/000077500000000000000000000000001360435400500202155ustar00rootroot00000000000000dub-1.19.0/test/issue346-redundant-flags/b/dub.json000066400000000000000000000000201360435400500216520ustar00rootroot00000000000000{ "name": "b" }dub-1.19.0/test/issue346-redundant-flags/b/source/000077500000000000000000000000001360435400500215155ustar00rootroot00000000000000dub-1.19.0/test/issue346-redundant-flags/b/source/b.d000066400000000000000000000000331360435400500220770ustar00rootroot00000000000000module b; void bfun() { } dub-1.19.0/test/issue346-redundant-flags/main/000077500000000000000000000000001360435400500207205ustar00rootroot00000000000000dub-1.19.0/test/issue346-redundant-flags/main/dub.json000066400000000000000000000001331360435400500223620ustar00rootroot00000000000000{ "name": "main", "dependencies": { "a": {"path": "../a"}, "b": {"path": "../b"} } }dub-1.19.0/test/issue346-redundant-flags/main/source/000077500000000000000000000000001360435400500222205ustar00rootroot00000000000000dub-1.19.0/test/issue346-redundant-flags/main/source/main.d000066400000000000000000000000661360435400500233130ustar00rootroot00000000000000import a; import b; void main() { afun(); bfun(); }dub-1.19.0/test/issue361-optional-deps.sh000077500000000000000000000013101360435400500200230ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue361-optional-deps rm -rf a/.dub rm -rf a/b/.dub rm -rf main1/.dub rm -rf main2/.dub rm -f main1/dub.selections.json ${DUB} build --bare --compiler=${DC} main1 echo "{" > cmp.tmp echo " \"fileVersion\": 1," >> cmp.tmp echo " \"versions\": {" >> cmp.tmp echo " \"b\": \"~master\"" >> cmp.tmp echo " }" >> cmp.tmp echo "}" >> cmp.tmp diff cmp.tmp main1/dub.selections.json ${DUB} build --bare --compiler=${DC} main2 echo "{" > cmp.tmp echo " \"fileVersion\": 1," >> cmp.tmp echo " \"versions\": {" >> cmp.tmp echo " \"a\": \"~master\"" >> cmp.tmp echo " }" >> cmp.tmp echo "}" >> cmp.tmp diff cmp.tmp main2/dub.selections.json dub-1.19.0/test/issue361-optional-deps/000077500000000000000000000000001360435400500174715ustar00rootroot00000000000000dub-1.19.0/test/issue361-optional-deps/.no_build000066400000000000000000000000001360435400500212530ustar00rootroot00000000000000dub-1.19.0/test/issue361-optional-deps/a/000077500000000000000000000000001360435400500177115ustar00rootroot00000000000000dub-1.19.0/test/issue361-optional-deps/a/dub.sdl000066400000000000000000000000101360435400500211560ustar00rootroot00000000000000name "a"dub-1.19.0/test/issue361-optional-deps/a/src/000077500000000000000000000000001360435400500205005ustar00rootroot00000000000000dub-1.19.0/test/issue361-optional-deps/a/src/a.d000066400000000000000000000000001360435400500210530ustar00rootroot00000000000000dub-1.19.0/test/issue361-optional-deps/b/000077500000000000000000000000001360435400500177125ustar00rootroot00000000000000dub-1.19.0/test/issue361-optional-deps/b/dub.sdl000066400000000000000000000000101360435400500211570ustar00rootroot00000000000000name "b"dub-1.19.0/test/issue361-optional-deps/b/src/000077500000000000000000000000001360435400500205015ustar00rootroot00000000000000dub-1.19.0/test/issue361-optional-deps/b/src/b.d000066400000000000000000000000001360435400500210550ustar00rootroot00000000000000dub-1.19.0/test/issue361-optional-deps/main1/000077500000000000000000000000001360435400500204765ustar00rootroot00000000000000dub-1.19.0/test/issue361-optional-deps/main1/dub.sdl000066400000000000000000000001531360435400500217530ustar00rootroot00000000000000name "main1" dependency "a" version="*" optional=true dependency "b" version="*" optional=true default=truedub-1.19.0/test/issue361-optional-deps/main1/src/000077500000000000000000000000001360435400500212655ustar00rootroot00000000000000dub-1.19.0/test/issue361-optional-deps/main1/src/main1.d000066400000000000000000000000001360435400500224250ustar00rootroot00000000000000dub-1.19.0/test/issue361-optional-deps/main2/000077500000000000000000000000001360435400500204775ustar00rootroot00000000000000dub-1.19.0/test/issue361-optional-deps/main2/dub.sdl000066400000000000000000000001531360435400500217540ustar00rootroot00000000000000name "main2" dependency "a" version="*" optional=true dependency "b" version="*" optional=true default=truedub-1.19.0/test/issue361-optional-deps/main2/dub.selections.json000066400000000000000000000000721360435400500243120ustar00rootroot00000000000000{ "fileVersion": 1, "versions": { "a": "~master" } } dub-1.19.0/test/issue361-optional-deps/main2/src/000077500000000000000000000000001360435400500212665ustar00rootroot00000000000000dub-1.19.0/test/issue361-optional-deps/main2/src/main2.d000066400000000000000000000000001360435400500224270ustar00rootroot00000000000000dub-1.19.0/test/issue502-root-import/000077500000000000000000000000001360435400500172035ustar00rootroot00000000000000dub-1.19.0/test/issue502-root-import/dub.json000066400000000000000000000001621360435400500206470ustar00rootroot00000000000000{ "name": "issue502-root-import", "dependencies": { "gitcompatibledubpackage": "~>1.0" } }dub-1.19.0/test/issue502-root-import/source/000077500000000000000000000000001360435400500205035ustar00rootroot00000000000000dub-1.19.0/test/issue502-root-import/source/app.d000066400000000000000000000001731360435400500214310ustar00rootroot00000000000000import gitcompatibledubpackage.subdir.file; void main(string[] args) { } unittest { assert(!hasTheWorldExploded()); }dub-1.19.0/test/issue564-invalid-upgrade-dependency.sh000077500000000000000000000003261360435400500224470ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue564-invalid-upgrade-dependency rm -rf a-1.0.0/.dub rm -rf a-1.1.0/.dub rm -rf main/.dub ${DUB} build --bare --compiler=${DC} main dub-1.19.0/test/issue564-invalid-upgrade-dependency/000077500000000000000000000000001360435400500221075ustar00rootroot00000000000000dub-1.19.0/test/issue564-invalid-upgrade-dependency/.no_build000066400000000000000000000000001360435400500236710ustar00rootroot00000000000000dub-1.19.0/test/issue564-invalid-upgrade-dependency/.no_run000066400000000000000000000000001360435400500233760ustar00rootroot00000000000000dub-1.19.0/test/issue564-invalid-upgrade-dependency/.no_test000066400000000000000000000000001360435400500235510ustar00rootroot00000000000000dub-1.19.0/test/issue564-invalid-upgrade-dependency/a-1.0.0/000077500000000000000000000000001360435400500227615ustar00rootroot00000000000000dub-1.19.0/test/issue564-invalid-upgrade-dependency/a-1.0.0/dub.json000066400000000000000000000000471360435400500244270ustar00rootroot00000000000000{ "name": "a", "version": "1.0.0", } dub-1.19.0/test/issue564-invalid-upgrade-dependency/a-1.0.0/source/000077500000000000000000000000001360435400500242615ustar00rootroot00000000000000dub-1.19.0/test/issue564-invalid-upgrade-dependency/a-1.0.0/source/a.d000066400000000000000000000000211360435400500246370ustar00rootroot00000000000000void test() { }dub-1.19.0/test/issue564-invalid-upgrade-dependency/a-1.1.0/000077500000000000000000000000001360435400500227625ustar00rootroot00000000000000dub-1.19.0/test/issue564-invalid-upgrade-dependency/a-1.1.0/dub.json000066400000000000000000000001361360435400500244270ustar00rootroot00000000000000{ "name": "a", "version": "1.1.0", "dependencies": { "invalid": {"path": "invalid"} } } dub-1.19.0/test/issue564-invalid-upgrade-dependency/a-1.1.0/source/000077500000000000000000000000001360435400500242625ustar00rootroot00000000000000dub-1.19.0/test/issue564-invalid-upgrade-dependency/a-1.1.0/source/a.d000066400000000000000000000000211360435400500246400ustar00rootroot00000000000000void test() { }dub-1.19.0/test/issue564-invalid-upgrade-dependency/main/000077500000000000000000000000001360435400500230335ustar00rootroot00000000000000dub-1.19.0/test/issue564-invalid-upgrade-dependency/main/dub.json000066400000000000000000000000721360435400500244770ustar00rootroot00000000000000{ "name": "main", "dependencies": { "a": "~>1.0" } } dub-1.19.0/test/issue564-invalid-upgrade-dependency/main/dub.selections.json000066400000000000000000000000701360435400500266440ustar00rootroot00000000000000{ "fileVersion": 1, "versions": { "a": "1.0.0" } } dub-1.19.0/test/issue564-invalid-upgrade-dependency/main/source/000077500000000000000000000000001360435400500243335ustar00rootroot00000000000000dub-1.19.0/test/issue564-invalid-upgrade-dependency/main/source/app.d000066400000000000000000000000521360435400500252550ustar00rootroot00000000000000import a; void main() { test(); } dub-1.19.0/test/issue586-subpack-dep.sh000077500000000000000000000003451360435400500174630ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue586-subpack-dep rm -rf a/.dub rm -rf a/b/.dub rm -rf main/.dub ${DUB} build --bare --compiler=${DC} main ${DUB} run --bare --compiler=${DC} main dub-1.19.0/test/issue586-subpack-dep/000077500000000000000000000000001360435400500171225ustar00rootroot00000000000000dub-1.19.0/test/issue586-subpack-dep/.no_build000066400000000000000000000000001360435400500207040ustar00rootroot00000000000000dub-1.19.0/test/issue586-subpack-dep/.no_run000066400000000000000000000000001360435400500204110ustar00rootroot00000000000000dub-1.19.0/test/issue586-subpack-dep/.no_test000066400000000000000000000000001360435400500205640ustar00rootroot00000000000000dub-1.19.0/test/issue586-subpack-dep/a/000077500000000000000000000000001360435400500173425ustar00rootroot00000000000000dub-1.19.0/test/issue586-subpack-dep/a/b/000077500000000000000000000000001360435400500175635ustar00rootroot00000000000000dub-1.19.0/test/issue586-subpack-dep/a/b/dub.sdl000066400000000000000000000000111360435400500210310ustar00rootroot00000000000000name "b" dub-1.19.0/test/issue586-subpack-dep/a/b/source/000077500000000000000000000000001360435400500210635ustar00rootroot00000000000000dub-1.19.0/test/issue586-subpack-dep/a/b/source/b.d000066400000000000000000000000431360435400500214460ustar00rootroot00000000000000module b; int bfun() { return 2; }dub-1.19.0/test/issue586-subpack-dep/a/dub.sdl000066400000000000000000000000651360435400500206210ustar00rootroot00000000000000name "a" dependency ":b" version="*" subPackage "b/" dub-1.19.0/test/issue586-subpack-dep/a/source/000077500000000000000000000000001360435400500206425ustar00rootroot00000000000000dub-1.19.0/test/issue586-subpack-dep/a/source/a.d000066400000000000000000000000711360435400500212250ustar00rootroot00000000000000module a; import b; int afun() { return 1 + bfun(); } dub-1.19.0/test/issue586-subpack-dep/main/000077500000000000000000000000001360435400500200465ustar00rootroot00000000000000dub-1.19.0/test/issue586-subpack-dep/main/dub.sdl000066400000000000000000000000761360435400500213270ustar00rootroot00000000000000name "main" dependency "a" version="*" targetType "executable"dub-1.19.0/test/issue586-subpack-dep/main/dub.selections.json000066400000000000000000000000721360435400500236610ustar00rootroot00000000000000{ "fileVersion": 1, "versions": { "a": "~master" } } dub-1.19.0/test/issue586-subpack-dep/main/source/000077500000000000000000000000001360435400500213465ustar00rootroot00000000000000dub-1.19.0/test/issue586-subpack-dep/main/source/c.d000066400000000000000000000000741360435400500217360ustar00rootroot00000000000000module c; import a; void main() { assert(afun() == 3); } dub-1.19.0/test/issue613-dynlib-pic.sh000077500000000000000000000003451360435400500173060ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue613-dynlib-pic rm -rf .dub if [ "${DC}" = "dmd" ]; then ${DUB} build --compiler=${DC} else echo "Skipping shared library test for ${DC}..." fi dub-1.19.0/test/issue613-dynlib-pic/000077500000000000000000000000001360435400500167455ustar00rootroot00000000000000dub-1.19.0/test/issue613-dynlib-pic/.gitignore000066400000000000000000000000461360435400500207350ustar00rootroot00000000000000.dub docs.json __dummy.html *.o *.obj dub-1.19.0/test/issue613-dynlib-pic/.no_build000066400000000000000000000000001360435400500205270ustar00rootroot00000000000000dub-1.19.0/test/issue613-dynlib-pic/.no_run000066400000000000000000000000001360435400500202340ustar00rootroot00000000000000dub-1.19.0/test/issue613-dynlib-pic/.no_test000066400000000000000000000000001360435400500204070ustar00rootroot00000000000000dub-1.19.0/test/issue613-dynlib-pic/dub.sdl000066400000000000000000000002601360435400500202210ustar00rootroot00000000000000name "issue613-dynlib-pic" targetType "dynamicLibrary" // TODO: instead of just testing build success, test if -shared, -fPIC and -defaultlib have all been specified correctlydub-1.19.0/test/issue613-dynlib-pic/source/000077500000000000000000000000001360435400500202455ustar00rootroot00000000000000dub-1.19.0/test/issue613-dynlib-pic/source/app.d000066400000000000000000000000201360435400500211620ustar00rootroot00000000000000void test() { }dub-1.19.0/test/issue616-describe-vs-generate-commands.sh000077500000000000000000000017441360435400500230600ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd "$CURR_DIR"/issue616-describe-vs-generate-commands temp_file=$(mktemp $(basename $0).XXXXXX) function cleanup { rm $temp_file } trap cleanup EXIT if ! $DUB describe --compiler=$DC --data-list --data=target-name \ > "$temp_file" 2>&1; then die 'Printing project data failed!' fi # Create the expected output file to compare stdout against. expected_file="$CURR_DIR/expected-issue616-output" echo "preGenerateCommands: DUB_PACKAGES_USED=issue616-describe-vs-generate-commands,issue616-subpack,issue616-subsubpack" > "$expected_file" echo "$CURR_DIR/issue616-describe-vs-generate-commands/src/" >> "$expected_file" echo "$CURR_DIR/issue616-subpack/src/" >> "$expected_file" echo "$CURR_DIR/issue616-subsubpack/src/" >> "$expected_file" echo "issue616-describe-vs-generate-commands" >> "$expected_file" if ! diff "$expected_file" "$temp_file"; then die 'The stdout output did not match the expected output!' fi dub-1.19.0/test/issue616-describe-vs-generate-commands/000077500000000000000000000000001360435400500225135ustar00rootroot00000000000000dub-1.19.0/test/issue616-describe-vs-generate-commands/.no_build000066400000000000000000000000021360435400500242770ustar00rootroot00000000000000 dub-1.19.0/test/issue616-describe-vs-generate-commands/do-preGenerateCommands.sh000077500000000000000000000005711360435400500274000ustar00rootroot00000000000000#!/usr/bin/env bash if [ -n "${dub_issue616}" ]; then echo 'Fail! preGenerateCommands recursion detected!' >&2 exit 0 # Don't return a non-zero error code here. This way the test gives a better diagnostic. fi echo preGenerateCommands: DUB_PACKAGES_USED=$DUB_PACKAGES_USED >&2 export dub_issue616=true $DUB describe --compiler=$DC --data-list --data=import-paths >&2 dub-1.19.0/test/issue616-describe-vs-generate-commands/dub.json000066400000000000000000000004731360435400500241640ustar00rootroot00000000000000{ "name": "issue616-describe-vs-generate-commands", "targetType": "executable", "preGenerateCommands-posix": ["cd $PACKAGE_DIR && ./do-preGenerateCommands.sh"], "dependencies": { "issue616-subpack": { "version": "1.0", "path": "../issue616-subpack" } } } dub-1.19.0/test/issue616-describe-vs-generate-commands/src/000077500000000000000000000000001360435400500233025ustar00rootroot00000000000000dub-1.19.0/test/issue616-describe-vs-generate-commands/src/dummy.d000066400000000000000000000000011360435400500245710ustar00rootroot00000000000000 dub-1.19.0/test/issue616-subpack/000077500000000000000000000000001360435400500163465ustar00rootroot00000000000000dub-1.19.0/test/issue616-subpack/.no_build000066400000000000000000000000021360435400500201320ustar00rootroot00000000000000 dub-1.19.0/test/issue616-subpack/dub.json000066400000000000000000000003231360435400500200110ustar00rootroot00000000000000{ "name": "issue616-subpack", "targetType": "library", "dependencies": { "issue616-subsubpack": { "version": "1.0", "path": "../issue616-subsubpack" } } } dub-1.19.0/test/issue616-subpack/src/000077500000000000000000000000001360435400500171355ustar00rootroot00000000000000dub-1.19.0/test/issue616-subpack/src/dummy.d000066400000000000000000000000011360435400500204240ustar00rootroot00000000000000 dub-1.19.0/test/issue616-subsubpack/000077500000000000000000000000001360435400500170605ustar00rootroot00000000000000dub-1.19.0/test/issue616-subsubpack/.no_build000066400000000000000000000000021360435400500206440ustar00rootroot00000000000000 dub-1.19.0/test/issue616-subsubpack/dub.json000066400000000000000000000001031360435400500205170ustar00rootroot00000000000000{ "name": "issue616-subsubpack", "targetType": "library" } dub-1.19.0/test/issue616-subsubpack/src/000077500000000000000000000000001360435400500176475ustar00rootroot00000000000000dub-1.19.0/test/issue616-subsubpack/src/dummy.d000066400000000000000000000000011360435400500211360ustar00rootroot00000000000000 dub-1.19.0/test/issue672-upgrade-optional.sh000077500000000000000000000005061360435400500205320ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue672-upgrade-optional rm -rf b/.dub echo "{\"fileVersion\": 1,\"versions\": {\"dub\": \"1.0.0\"}}" > dub.selections.json ${DUB} upgrade if ! grep -c -e "\"dub\": \"1.1.0\"" dub.selections.json; then die $LINENO 'Dependency not upgraded.' fi dub-1.19.0/test/issue672-upgrade-optional/000077500000000000000000000000001360435400500201725ustar00rootroot00000000000000dub-1.19.0/test/issue672-upgrade-optional/.no_build000066400000000000000000000000001360435400500217540ustar00rootroot00000000000000dub-1.19.0/test/issue672-upgrade-optional/dub.sdl000066400000000000000000000001021360435400500214410ustar00rootroot00000000000000name "b" dependency "dub" version=">=1.0.0 <=1.1.0" optional=true dub-1.19.0/test/issue672-upgrade-optional/dub.selections.json000066400000000000000000000000721360435400500240050ustar00rootroot00000000000000{ "fileVersion": 1, "versions": { "dub": "1.1.0" } } dub-1.19.0/test/issue674-concurrent-dub.sh000077500000000000000000000005401360435400500202120ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh TMPDIR=$(mktemp -d $(basename $0).XXXXXX) function cleanup { rm -rf ${TMPDIR} } trap cleanup EXIT cd ${TMPDIR} && $DUB fetch --cache=local bloom & pid1=$! sleep 0.5 cd ${TMPDIR} && $DUB fetch --cache=local bloom & pid2=$! wait $pid1 wait $pid2 [ -d ${TMPDIR}/.dub/packages/bloom* ]dub-1.19.0/test/issue686-multiple-march.sh000077500000000000000000000003131360435400500202040ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue686-multiple-march ${DUB} build --bare --force --compiler=${DC} -a x86_64 -v main 2>&1 | { ! grep -e '-m64 -m64' -c; } dub-1.19.0/test/issue686-multiple-march/000077500000000000000000000000001360435400500176505ustar00rootroot00000000000000dub-1.19.0/test/issue686-multiple-march/.no_build000066400000000000000000000000001360435400500214320ustar00rootroot00000000000000dub-1.19.0/test/issue686-multiple-march/.no_run000066400000000000000000000000001360435400500211370ustar00rootroot00000000000000dub-1.19.0/test/issue686-multiple-march/.no_test000066400000000000000000000000001360435400500213120ustar00rootroot00000000000000dub-1.19.0/test/issue686-multiple-march/a/000077500000000000000000000000001360435400500200705ustar00rootroot00000000000000dub-1.19.0/test/issue686-multiple-march/a/dub.json000066400000000000000000000000771360435400500215410ustar00rootroot00000000000000{ "name": "a", "dependencies": { "b": {"path": "../b"} } }dub-1.19.0/test/issue686-multiple-march/a/source/000077500000000000000000000000001360435400500213705ustar00rootroot00000000000000dub-1.19.0/test/issue686-multiple-march/a/source/a.d000066400000000000000000000000331360435400500217510ustar00rootroot00000000000000module a; void afun() { } dub-1.19.0/test/issue686-multiple-march/b/000077500000000000000000000000001360435400500200715ustar00rootroot00000000000000dub-1.19.0/test/issue686-multiple-march/b/dub.json000066400000000000000000000000201360435400500215260ustar00rootroot00000000000000{ "name": "b" }dub-1.19.0/test/issue686-multiple-march/b/source/000077500000000000000000000000001360435400500213715ustar00rootroot00000000000000dub-1.19.0/test/issue686-multiple-march/b/source/b.d000066400000000000000000000000331360435400500217530ustar00rootroot00000000000000module b; void bfun() { } dub-1.19.0/test/issue686-multiple-march/main/000077500000000000000000000000001360435400500205745ustar00rootroot00000000000000dub-1.19.0/test/issue686-multiple-march/main/dub.json000066400000000000000000000001331360435400500222360ustar00rootroot00000000000000{ "name": "main", "dependencies": { "a": {"path": "../a"}, "b": {"path": "../b"} } }dub-1.19.0/test/issue686-multiple-march/main/source/000077500000000000000000000000001360435400500220745ustar00rootroot00000000000000dub-1.19.0/test/issue686-multiple-march/main/source/main.d000066400000000000000000000000661360435400500231670ustar00rootroot00000000000000import a; import b; void main() { afun(); bfun(); }dub-1.19.0/test/issue754-path-selection-fail/000077500000000000000000000000001360435400500205515ustar00rootroot00000000000000dub-1.19.0/test/issue754-path-selection-fail/a-1.0/000077500000000000000000000000001360435400500212655ustar00rootroot00000000000000dub-1.19.0/test/issue754-path-selection-fail/a-1.0/dub.sdl000066400000000000000000000000311360435400500225350ustar00rootroot00000000000000name "a" version "1.0.0" dub-1.19.0/test/issue754-path-selection-fail/a-1.0/source/000077500000000000000000000000001360435400500225655ustar00rootroot00000000000000dub-1.19.0/test/issue754-path-selection-fail/a-1.0/source/a.d000066400000000000000000000000311360435400500231440ustar00rootroot00000000000000module a; void test() {}dub-1.19.0/test/issue754-path-selection-fail/a-2.0/000077500000000000000000000000001360435400500212665ustar00rootroot00000000000000dub-1.19.0/test/issue754-path-selection-fail/a-2.0/dub.sdl000066400000000000000000000000321360435400500225370ustar00rootroot00000000000000name "a" version "2.0.0" dub-1.19.0/test/issue754-path-selection-fail/dub.sdl000066400000000000000000000000501360435400500220220ustar00rootroot00000000000000name "test" dependency "a" path="a-2.0" dub-1.19.0/test/issue754-path-selection-fail/dub.selections.json000066400000000000000000000001021360435400500243560ustar00rootroot00000000000000{ "fileVersion": 1, "versions": { "a": {"path": "a-1.0"} } } dub-1.19.0/test/issue754-path-selection-fail/source/000077500000000000000000000000001360435400500220515ustar00rootroot00000000000000dub-1.19.0/test/issue754-path-selection-fail/source/app.d000066400000000000000000000000441360435400500227740ustar00rootroot00000000000000import a; void main() { test(); } dub-1.19.0/test/issue777-bogus-path-dependency/000077500000000000000000000000001360435400500211135ustar00rootroot00000000000000dub-1.19.0/test/issue777-bogus-path-dependency/b/000077500000000000000000000000001360435400500213345ustar00rootroot00000000000000dub-1.19.0/test/issue777-bogus-path-dependency/b/a.d000066400000000000000000000000001360435400500217070ustar00rootroot00000000000000dub-1.19.0/test/issue777-bogus-path-dependency/b/dub.sdl000066400000000000000000000002051360435400500226070ustar00rootroot00000000000000name "b" targetType "none" configuration "a" { dependency "c" version="*" } configuration "b" { dependency "c" path="../c-err" } dub-1.19.0/test/issue777-bogus-path-dependency/c-err/000077500000000000000000000000001360435400500221235ustar00rootroot00000000000000dub-1.19.0/test/issue777-bogus-path-dependency/c-err/dub.sdl000066400000000000000000000000111360435400500233710ustar00rootroot00000000000000name "c" dub-1.19.0/test/issue777-bogus-path-dependency/c-err/source/000077500000000000000000000000001360435400500234235ustar00rootroot00000000000000dub-1.19.0/test/issue777-bogus-path-dependency/c-err/source/lib.d000066400000000000000000000000411360435400500243310ustar00rootroot00000000000000module lib; void c() { error } dub-1.19.0/test/issue777-bogus-path-dependency/c/000077500000000000000000000000001360435400500213355ustar00rootroot00000000000000dub-1.19.0/test/issue777-bogus-path-dependency/c/dub.sdl000066400000000000000000000000111360435400500226030ustar00rootroot00000000000000name "c" dub-1.19.0/test/issue777-bogus-path-dependency/c/source/000077500000000000000000000000001360435400500226355ustar00rootroot00000000000000dub-1.19.0/test/issue777-bogus-path-dependency/c/source/lib.d000066400000000000000000000000321360435400500235430ustar00rootroot00000000000000module lib; void c() { } dub-1.19.0/test/issue777-bogus-path-dependency/dub.sdl000066400000000000000000000000441360435400500223670ustar00rootroot00000000000000name "test" dependency "b" path="b" dub-1.19.0/test/issue777-bogus-path-dependency/dub.selections.json000066400000000000000000000001221360435400500247220ustar00rootroot00000000000000{ "fileVersion": 1, "versions": { "b": {"path":"b"}, "c": {"path":"c"} } } dub-1.19.0/test/issue777-bogus-path-dependency/source/000077500000000000000000000000001360435400500224135ustar00rootroot00000000000000dub-1.19.0/test/issue777-bogus-path-dependency/source/app.d000066400000000000000000000000431360435400500233350ustar00rootroot00000000000000import lib; void main() { c(); } dub-1.19.0/test/issue782-gtkd-pkg-config.sh000077500000000000000000000020401360435400500202300ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh if [ "${DC}" != "dmd" ]; then echo "Skipping issue782-dtkd-pkg-config test for ${DC}..." else echo ${CURR_DIR-$(pwd)} # the ${CURR_DIR-$(pwd)} allows running issue782-gtkd-pkg-config.sh stand-alone from the test directory cd ${CURR_DIR-$(pwd)}/issue782-gtkd-pkg-config rm -rf fake-gtkd/.dub rm -f fake-gtkd/libfake-gtkd.so rm -rf main/.dub rm -f main/fake-gtkd-test echo ${DUB} cd fake-gtkd && ${DUB} build --compiler=${DC} cd ../main # `run` needs to find the fake-gtkd shared library, so set LD_LIBRARY_PATH to where it is export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-}${LD_LIBRARY_PATH:+:}$PWD/../fake-gtkd # pkg-config needs to find our .pc file which is in $PWD/../fake-gtkd/pkgconfig, so set PKG_CONFIG_PATH accordingly export PKG_CONFIG_PATH=$PWD/../fake-gtkd/pkgconfig ${DUB} run --force --compiler=${DC} cd .. rm -rf fake-gtkd/.dub rm fake-gtkd/libfake-gtkd.so rm -rf main/.dub rm main/fake-gtkd-test fi dub-1.19.0/test/issue782-gtkd-pkg-config.sh.min_frontend000066400000000000000000000000051360435400500227050ustar00rootroot000000000000002.068dub-1.19.0/test/issue782-gtkd-pkg-config/000077500000000000000000000000001360435400500176755ustar00rootroot00000000000000dub-1.19.0/test/issue782-gtkd-pkg-config/.no_build000066400000000000000000000000001360435400500214570ustar00rootroot00000000000000dub-1.19.0/test/issue782-gtkd-pkg-config/.no_run000066400000000000000000000000001360435400500211640ustar00rootroot00000000000000dub-1.19.0/test/issue782-gtkd-pkg-config/.no_test000066400000000000000000000000001360435400500213370ustar00rootroot00000000000000dub-1.19.0/test/issue782-gtkd-pkg-config/fake-gtkd/000077500000000000000000000000001360435400500215325ustar00rootroot00000000000000dub-1.19.0/test/issue782-gtkd-pkg-config/fake-gtkd/dub.json000066400000000000000000000001761360435400500232030ustar00rootroot00000000000000{ "name" : "fake-gtkd", "targetType": "dynamicLibrary", "description" : "Fake GtkD shared library for testing", } dub-1.19.0/test/issue782-gtkd-pkg-config/fake-gtkd/pkgconfig/000077500000000000000000000000001360435400500235015ustar00rootroot00000000000000dub-1.19.0/test/issue782-gtkd-pkg-config/fake-gtkd/pkgconfig/fake-gtkd.pc000066400000000000000000000010371360435400500256630ustar00rootroot00000000000000prefix=../fake-gtkd libdir=${prefix} includedir=${prefix}/src Name: fake-gtkd Description: Fake GtkD shared library for testing Version: 1.0.0 #Requires: phobos2 # The "-L-defaultlib=libphobos2.so" and "-defaultlib=libphobos2.so" should both end up on the compiler (at link stage) invocation as "-defaultlib=libphobos2.so" # For this test, it doesn't hurt that they appear twice on the cmd line... Libs: -L-L${libdir} -L-l:libfake-gtkd.so -L-l:libdl.so.2 -pthread -L-defaultlib=libphobos2.so -defaultlib=libphobos2.so Cflags: -I${includedir} dub-1.19.0/test/issue782-gtkd-pkg-config/fake-gtkd/src/000077500000000000000000000000001360435400500223215ustar00rootroot00000000000000dub-1.19.0/test/issue782-gtkd-pkg-config/fake-gtkd/src/fakegtkd.d000066400000000000000000000001121360435400500242400ustar00rootroot00000000000000extern (C) string test_function() { return "Fake GtkD shared library"; }dub-1.19.0/test/issue782-gtkd-pkg-config/fake-gtkd/src/lib.d000066400000000000000000000000001360435400500232220ustar00rootroot00000000000000dub-1.19.0/test/issue782-gtkd-pkg-config/main/000077500000000000000000000000001360435400500206215ustar00rootroot00000000000000dub-1.19.0/test/issue782-gtkd-pkg-config/main/dub.json000066400000000000000000000003151360435400500222650ustar00rootroot00000000000000{ "name" : "fake-gtkd-test", "description" : "Small test executable calling a Fake GtkD shared library function for testing", "importPaths" : ["../fake-gtkd/src"], "libs" : ["fake-gtkd"] } dub-1.19.0/test/issue782-gtkd-pkg-config/main/src/000077500000000000000000000000001360435400500214105ustar00rootroot00000000000000dub-1.19.0/test/issue782-gtkd-pkg-config/main/src/app.d000066400000000000000000000001321360435400500223310ustar00rootroot00000000000000import std.stdio; import fakegtkd; int main() { writeln(test_function()); return 0; }dub-1.19.0/test/issue813-fixed-dependency.sh000077500000000000000000000003101360435400500204610ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue813-fixed-dependency rm -rf main/.dub rm -rf sub/.dub rm -rf sub/sub/.dub ${DUB} build --bare --compiler=${DC} main dub-1.19.0/test/issue813-fixed-dependency/000077500000000000000000000000001360435400500201305ustar00rootroot00000000000000dub-1.19.0/test/issue813-fixed-dependency/.no_build000066400000000000000000000000021360435400500217140ustar00rootroot00000000000000 dub-1.19.0/test/issue813-fixed-dependency/main/000077500000000000000000000000001360435400500210545ustar00rootroot00000000000000dub-1.19.0/test/issue813-fixed-dependency/main/dub.sdl000066400000000000000000000001011360435400500223220ustar00rootroot00000000000000name "main" targetType "executable" dependency "sub" version="*" dub-1.19.0/test/issue813-fixed-dependency/main/dub.selections.json000066400000000000000000000001051360435400500246640ustar00rootroot00000000000000{ "fileVersion": 1, "versions": { "sub": {"path": "../sub"} } } dub-1.19.0/test/issue813-fixed-dependency/main/src/000077500000000000000000000000001360435400500216435ustar00rootroot00000000000000dub-1.19.0/test/issue813-fixed-dependency/main/src/app.d000066400000000000000000000000521360435400500225650ustar00rootroot00000000000000import sub.test; void main() { foo(); } dub-1.19.0/test/issue813-fixed-dependency/sub/000077500000000000000000000000001360435400500207215ustar00rootroot00000000000000dub-1.19.0/test/issue813-fixed-dependency/sub/dub.sdl000066400000000000000000000000731360435400500221770ustar00rootroot00000000000000name "sub" subPackage "sub/" dependency ":sub" version="*" dub-1.19.0/test/issue813-fixed-dependency/sub/sub/000077500000000000000000000000001360435400500215125ustar00rootroot00000000000000dub-1.19.0/test/issue813-fixed-dependency/sub/sub/dub.sdl000066400000000000000000000000131360435400500227620ustar00rootroot00000000000000name "sub" dub-1.19.0/test/issue813-fixed-dependency/sub/sub/src/000077500000000000000000000000001360435400500223015ustar00rootroot00000000000000dub-1.19.0/test/issue813-fixed-dependency/sub/sub/src/sub/000077500000000000000000000000001360435400500230725ustar00rootroot00000000000000dub-1.19.0/test/issue813-fixed-dependency/sub/sub/src/sub/test.d000066400000000000000000000000411360435400500242110ustar00rootroot00000000000000module sub.test; void foo() { }dub-1.19.0/test/issue813-pure-sub-dependency.sh000077500000000000000000000003521360435400500211320ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue813-pure-sub-dependency rm -rf main/.dub rm -rf sub/.dub rm -rf sub/sub/.dub rm -f main/dub.selections.json ${DUB} build --bare --compiler=${DC} main dub-1.19.0/test/issue813-pure-sub-dependency/000077500000000000000000000000001360435400500205735ustar00rootroot00000000000000dub-1.19.0/test/issue813-pure-sub-dependency/.no_build000066400000000000000000000000021360435400500223570ustar00rootroot00000000000000 dub-1.19.0/test/issue813-pure-sub-dependency/main/000077500000000000000000000000001360435400500215175ustar00rootroot00000000000000dub-1.19.0/test/issue813-pure-sub-dependency/main/dub.sdl000066400000000000000000000001051360435400500227710ustar00rootroot00000000000000name "main" targetType "executable" dependency "sub:sub" version="*" dub-1.19.0/test/issue813-pure-sub-dependency/main/src/000077500000000000000000000000001360435400500223065ustar00rootroot00000000000000dub-1.19.0/test/issue813-pure-sub-dependency/main/src/app.d000066400000000000000000000000521360435400500232300ustar00rootroot00000000000000import sub.test; void main() { foo(); } dub-1.19.0/test/issue813-pure-sub-dependency/sub/000077500000000000000000000000001360435400500213645ustar00rootroot00000000000000dub-1.19.0/test/issue813-pure-sub-dependency/sub/dub.sdl000066400000000000000000000000731360435400500226420ustar00rootroot00000000000000name "sub" subPackage "sub/" dependency ":sub" version="*" dub-1.19.0/test/issue813-pure-sub-dependency/sub/sub/000077500000000000000000000000001360435400500221555ustar00rootroot00000000000000dub-1.19.0/test/issue813-pure-sub-dependency/sub/sub/dub.sdl000066400000000000000000000000131360435400500234250ustar00rootroot00000000000000name "sub" dub-1.19.0/test/issue813-pure-sub-dependency/sub/sub/src/000077500000000000000000000000001360435400500227445ustar00rootroot00000000000000dub-1.19.0/test/issue813-pure-sub-dependency/sub/sub/src/sub/000077500000000000000000000000001360435400500235355ustar00rootroot00000000000000dub-1.19.0/test/issue813-pure-sub-dependency/sub/sub/src/sub/test.d000066400000000000000000000000411360435400500246540ustar00rootroot00000000000000module sub.test; void foo() { }dub-1.19.0/test/issue820-extra-fields-after-convert.sh000077500000000000000000000005441360435400500224210ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/1-exec-simple cp dub.json dub.json.bak ${DUB} convert -f sdl if grep -qe "version\|sourcePaths\|importPaths\|configuration" dub.sdl > /dev/null; then mv dub.json.bak dub.json rm dub.sdl die $LINENO 'Conversion added extra fields.' fi mv dub.json.bak dub.json rm dub.sdl dub-1.19.0/test/issue838-custom-cache-paths.sh000077500000000000000000000007341360435400500207570ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh CONFIG_FILE=$CURR_DIR/../etc/dub/settings.json mkdir $CURR_DIR/../etc && mkdir $CURR_DIR/../etc/dub || true echo "{\"customCachePaths\": [\"$CURR_DIR/issue838-custom-cache-paths/cache\"]}" > $CONFIG_FILE trap "rm $CONFIG_FILE" EXIT if ! { $DUB build --root "$CURR_DIR/issue838-custom-cache-paths" --skip-registry=all; }; then die $LINENO 'Failed to build package with custom cache path for dependencies.' fi dub-1.19.0/test/issue838-custom-cache-paths/000077500000000000000000000000001360435400500204145ustar00rootroot00000000000000dub-1.19.0/test/issue838-custom-cache-paths/.no_build000066400000000000000000000000001360435400500221760ustar00rootroot00000000000000dub-1.19.0/test/issue838-custom-cache-paths/cache/000077500000000000000000000000001360435400500214575ustar00rootroot00000000000000dub-1.19.0/test/issue838-custom-cache-paths/cache/foo-1.0.0/000077500000000000000000000000001360435400500226745ustar00rootroot00000000000000dub-1.19.0/test/issue838-custom-cache-paths/cache/foo-1.0.0/foo/000077500000000000000000000000001360435400500234575ustar00rootroot00000000000000dub-1.19.0/test/issue838-custom-cache-paths/cache/foo-1.0.0/foo/dub.sdl000066400000000000000000000000661360435400500247370ustar00rootroot00000000000000name "foo" version "1.0.0" targetType "sourceLibrary" dub-1.19.0/test/issue838-custom-cache-paths/dub.sdl000066400000000000000000000000551360435400500216720ustar00rootroot00000000000000name "test" dependency "foo" version="1.0.0" dub-1.19.0/test/issue838-custom-cache-paths/source/000077500000000000000000000000001360435400500217145ustar00rootroot00000000000000dub-1.19.0/test/issue838-custom-cache-paths/source/app.d000066400000000000000000000000201360435400500226310ustar00rootroot00000000000000void main() { } dub-1.19.0/test/issue877-auto-fetch-package-on-run.sh000077500000000000000000000021221360435400500221270ustar00rootroot00000000000000#!/bin/bash set -eu -o pipefail set -x $DUB remove --version="*" gitcompatibledubpackage || true # check whether the interactive run mode works echo "y" | $DUB run gitcompatibledubpackage | grep "Hello DUB" $DUB remove gitcompatibledubpackage ! (echo "n" | $DUB run gitcompatibledubpackage | grep "Hello DUB") ! $DUB remove gitcompatibledubpackage # check -y $DUB run --yes gitcompatibledubpackage | grep "Hello DUB" $DUB remove gitcompatibledubpackage # check --yes $DUB run -y gitcompatibledubpackage | grep "Hello DUB" $DUB remove gitcompatibledubpackage (! $DUB run --non-interactive gitcompatibledubpackage) 2>&1 | grep "Failed to find.*gitcompatibledubpackage.*locally" # check supplying versions directly dub_log="$($DUB run gitcompatibledubpackage@1.0.3)" echo "$dub_log" | grep "Hello DUB" echo "$dub_log" | grep "Fetching.*1.0.3" $DUB remove gitcompatibledubpackage # check supplying an invalid version (! $DUB run gitcompatibledubpackage@0.42.43) 2>&1 | \ grep 'No package gitcompatibledubpackage was found matching the dependency 0[.]42[.]43' ! $DUB remove gitcompatibledubpackage dub-1.19.0/test/issue884-init-defer-file-creation.sh000077500000000000000000000007161360435400500220350ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh TMPDIR=${CURR_DIR}tmppack echo $TMPDIR mkdir ${TMPDIR} cd ${TMPDIR} # kill dub init during interactive mode mkfifo in ${DUB} init < in & sleep 1 kill $! rm in # ensure that no files are left behind NFILES_PLUS_ONE=`ls -la | wc -l` cd ${CURR_DIR} rm -r ${TMPDIR} # ignore sum + "." + ".." if [ ${NFILES_PLUS_ONE} -gt 3 ]; then die $LINENO 'Aborted dub init left spurious files around.' fi dub-1.19.0/test/issue895-local-configuration.sh000077500000000000000000000053701360435400500212320ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh if [ -e /var/lib/dub/settings.json ]; then die $LINENO 'Found existing system wide DUB configuration. Aborting.' fi if [ -e ~/.dub/settings.json ]; then die $LINENO 'Found existing user wide DUB configuration. Aborting.' fi cd ${CURR_DIR} mkdir -p ../etc/dub echo "{\"defaultCompiler\": \"foo\"}" > ../etc/dub/settings.json echo "Empty file named foo." > ../bin/foo function cleanup { rm -r ../etc } trap cleanup EXIT if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "Unknown compiler: $(dirname $CURR_DIR)/bin/foo"; then rm ../bin/foo die $LINENO 'DUB did not find the local configuration with an adjacent compiler.' fi echo "{\"defaultCompiler\": \"$CURR_DIR/foo\"}" > ../etc/dub/settings.json mv ../bin/foo $CURR_DIR if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "Unknown compiler: $CURR_DIR/foo"; then rm $CURR_DIR/foo die $LINENO 'DUB did not find a locally-configured compiler with an absolute path.' fi echo "{\"defaultCompiler\": \"~/.dub/foo\"}" > ../etc/dub/settings.json mv $CURR_DIR/foo ~/.dub/ if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "Unknown compiler: "; then rm ~/.dub/foo die $LINENO 'DUB did not find a locally-configured compiler with a tilde-prefixed path.' fi echo "{\"defaultCompiler\": \"\$DUB_BINARY_PATH/../foo\"}" > ../etc/dub/settings.json mv ~/.dub/foo .. if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "Unknown compiler: $(dirname $CURR_DIR)/bin/../foo"; then rm ../foo die $LINENO 'DUB did not find a locally-configured compiler with a DUB-relative path.' fi echo "{\"defaultCompiler\": \"../foo\"}" > ../etc/dub/settings.json if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "defaultCompiler specified in a DUB config file cannot use an unqualified relative path"; then rm ../foo die $LINENO 'DUB did not error properly for a locally-configured compiler with a relative path.' fi rm ../etc/dub/settings.json echo "Empty file named ldc2." > ../bin/ldc2 if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "Failed to invoke the compiler $(dirname $CURR_DIR)/bin/ldc2 to determine the build platform"; then rm ../bin/ldc2 die $LINENO 'DUB did not find ldc2 adjacent to it.' fi echo "{\"defaultCompiler\": \"foo\"}" > ../etc/dub/settings.json rm ../bin/ldc2 export PATH=$(dirname $CURR_DIR)${PATH:+:$PATH} if ! { ${DUB} describe --single issue103-single-file-package.d 2>&1 || true; } | grep -cF "Unknown compiler: foo"; then rm ../foo die $LINENO 'DUB did not find a locally-configured compiler in its PATH.' fi rm ../foo dub-1.19.0/test/issue923-subpackage-deps.sh000077500000000000000000000005021360435400500203110ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue923-subpackage-deps rm -rf main/.dub rm -rf a/.dub rm -rf b/.dub rm -f main/dub.selections.json ${DUB} build --bare --compiler=${DC} main if ! grep -c -e \"b\" main/dub.selections.json; then die $LINENO 'Dependency b not resolved.' fi dub-1.19.0/test/issue923-subpackage-deps/000077500000000000000000000000001360435400500177555ustar00rootroot00000000000000dub-1.19.0/test/issue923-subpackage-deps/.no_build000066400000000000000000000000021360435400500215410ustar00rootroot00000000000000 dub-1.19.0/test/issue923-subpackage-deps/a/000077500000000000000000000000001360435400500201755ustar00rootroot00000000000000dub-1.19.0/test/issue923-subpackage-deps/a/dub.sdl000066400000000000000000000002271360435400500214540ustar00rootroot00000000000000name "a" dependency ":foo" version="*" subPackage { name "foo" dependency "b" version="*" } subPackage { name "bar" dependency "a" version="*" }dub-1.19.0/test/issue923-subpackage-deps/b/000077500000000000000000000000001360435400500201765ustar00rootroot00000000000000dub-1.19.0/test/issue923-subpackage-deps/b/dub.sdl000066400000000000000000000000101360435400500214430ustar00rootroot00000000000000name "b"dub-1.19.0/test/issue923-subpackage-deps/b/source/000077500000000000000000000000001360435400500214765ustar00rootroot00000000000000dub-1.19.0/test/issue923-subpackage-deps/b/source/b.d000066400000000000000000000000331360435400500220600ustar00rootroot00000000000000module b; void test() { } dub-1.19.0/test/issue923-subpackage-deps/main/000077500000000000000000000000001360435400500207015ustar00rootroot00000000000000dub-1.19.0/test/issue923-subpackage-deps/main/dub.sdl000066400000000000000000000000531360435400500221550ustar00rootroot00000000000000name "main" dependency "a:bar" version="*" dub-1.19.0/test/issue923-subpackage-deps/main/source/000077500000000000000000000000001360435400500222015ustar00rootroot00000000000000dub-1.19.0/test/issue923-subpackage-deps/main/source/app.d000066400000000000000000000000441360435400500231240ustar00rootroot00000000000000import b; void main() { test(); } dub-1.19.0/test/issue934-path-dep.sh000077500000000000000000000003231360435400500167600ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue934-path-dep rm -rf main/.dub rm -rf a/.dub rm -rf b/.dub rm -f main/dub.selections.json cd main ${DUB} build --compiler=${DC} dub-1.19.0/test/issue934-path-dep/000077500000000000000000000000001360435400500164235ustar00rootroot00000000000000dub-1.19.0/test/issue934-path-dep/.no_build000066400000000000000000000000021360435400500202070ustar00rootroot00000000000000 dub-1.19.0/test/issue934-path-dep/a/000077500000000000000000000000001360435400500166435ustar00rootroot00000000000000dub-1.19.0/test/issue934-path-dep/a/dub.sdl000066400000000000000000000000111360435400500201110ustar00rootroot00000000000000name "a" dub-1.19.0/test/issue934-path-dep/b/000077500000000000000000000000001360435400500166445ustar00rootroot00000000000000dub-1.19.0/test/issue934-path-dep/b/dub.sdl000066400000000000000000000000431360435400500201170ustar00rootroot00000000000000name "b" dependency "a" path="../a"dub-1.19.0/test/issue934-path-dep/b/source/000077500000000000000000000000001360435400500201445ustar00rootroot00000000000000dub-1.19.0/test/issue934-path-dep/b/source/b.d000066400000000000000000000000331360435400500205260ustar00rootroot00000000000000module b; void test() { } dub-1.19.0/test/issue934-path-dep/main/000077500000000000000000000000001360435400500173475ustar00rootroot00000000000000dub-1.19.0/test/issue934-path-dep/main/dub.sdl000066400000000000000000000001021360435400500206160ustar00rootroot00000000000000name "main" dependency "a" path="../a" dependency "b" path="../b" dub-1.19.0/test/issue934-path-dep/main/source/000077500000000000000000000000001360435400500206475ustar00rootroot00000000000000dub-1.19.0/test/issue934-path-dep/main/source/app.d000066400000000000000000000000441360435400500215720ustar00rootroot00000000000000import b; void main() { test(); } dub-1.19.0/test/issue959-path-based-subpack-dep/000077500000000000000000000000001360435400500211345ustar00rootroot00000000000000dub-1.19.0/test/issue959-path-based-subpack-dep/dub.sdl000066400000000000000000000001701360435400500224100ustar00rootroot00000000000000name "bar" mainSourceFile "main.d" targetType "executable" dependency "foo" path="foo" dependency "foo:baz" path="foo" dub-1.19.0/test/issue959-path-based-subpack-dep/foo/000077500000000000000000000000001360435400500217175ustar00rootroot00000000000000dub-1.19.0/test/issue959-path-based-subpack-dep/foo/dub.sdl000066400000000000000000000002031360435400500231700ustar00rootroot00000000000000name "foo" targetType "sourceLibrary" subPackage { name "baz" targetType "sourceLibrary" dependency "foo" path="." } dub-1.19.0/test/issue959-path-based-subpack-dep/main.d000066400000000000000000000000161360435400500222220ustar00rootroot00000000000000void main() {}dub-1.19.0/test/issue97-targettype-none-nodeps/000077500000000000000000000000001360435400500212545ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none-nodeps/.fail_build000066400000000000000000000000001360435400500233350ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none-nodeps/.gitignore000066400000000000000000000000461360435400500232440ustar00rootroot00000000000000.dub docs.json __dummy.html *.o *.obj dub-1.19.0/test/issue97-targettype-none-nodeps/.no_run000066400000000000000000000000001360435400500225430ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none-nodeps/a/000077500000000000000000000000001360435400500214745ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none-nodeps/a/dub.sdl000066400000000000000000000000411360435400500227450ustar00rootroot00000000000000name "a" targetType "executable" dub-1.19.0/test/issue97-targettype-none-nodeps/a/source/000077500000000000000000000000001360435400500227745ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none-nodeps/a/source/app.d000066400000000000000000000001311360435400500237140ustar00rootroot00000000000000import std.stdio; void main() { writeln("Edit source/app.d to start your project."); } dub-1.19.0/test/issue97-targettype-none-nodeps/b/000077500000000000000000000000001360435400500214755ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none-nodeps/b/dub.sdl000066400000000000000000000000411360435400500227460ustar00rootroot00000000000000name "b" targetType "executable" dub-1.19.0/test/issue97-targettype-none-nodeps/b/source/000077500000000000000000000000001360435400500227755ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none-nodeps/b/source/app.d000066400000000000000000000001311360435400500237150ustar00rootroot00000000000000import std.stdio; void main() { writeln("Edit source/app.d to start your project."); } dub-1.19.0/test/issue97-targettype-none-nodeps/dub.sdl000066400000000000000000000001251360435400500225300ustar00rootroot00000000000000name "issue97-targettype-none" targetType "none" subPackage "./a/" subPackage "./b/" dub-1.19.0/test/issue97-targettype-none-onerecipe/000077500000000000000000000000001360435400500217355ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none-onerecipe/.gitignore000066400000000000000000000000461360435400500237250ustar00rootroot00000000000000.dub docs.json __dummy.html *.o *.obj dub-1.19.0/test/issue97-targettype-none-onerecipe/.no_run000066400000000000000000000000001360435400500232240ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none-onerecipe/a/000077500000000000000000000000001360435400500221555ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none-onerecipe/a/source/000077500000000000000000000000001360435400500234555ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none-onerecipe/a/source/app.d000066400000000000000000000001311360435400500243750ustar00rootroot00000000000000import std.stdio; void main() { writeln("Edit source/app.d to start your project."); } dub-1.19.0/test/issue97-targettype-none-onerecipe/b/000077500000000000000000000000001360435400500221565ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none-onerecipe/b/source/000077500000000000000000000000001360435400500234565ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none-onerecipe/b/source/app.d000066400000000000000000000001311360435400500243760ustar00rootroot00000000000000import std.stdio; void main() { writeln("Edit source/app.d to start your project."); } dub-1.19.0/test/issue97-targettype-none-onerecipe/dub.sdl000066400000000000000000000004531360435400500232150ustar00rootroot00000000000000name "issue97-targettype-none" targetType "none" dependency "issue97-targettype-none:a" version="*" dependency "issue97-targettype-none:b" version="*" subPackage { name "a" targetType "executable" sourcePaths "a/source" } subPackage { name "b" targetType "executable" sourcePaths "b/source" } dub-1.19.0/test/issue97-targettype-none.sh000077500000000000000000000006001360435400500203210ustar00rootroot00000000000000#!/usr/bin/env bash set -e ${DUB} build --root ${CURR_DIR}/issue97-targettype-none 2>&1 || true # make sure both sub-packages are cleaned OUTPUT=`${DUB} clean --root ${CURR_DIR}/issue97-targettype-none 2>&1` echo $OUTPUT | grep -c "Cleaning package at .*/issue97-targettype-none/a/" > /dev/null echo $OUTPUT | grep -c "Cleaning package at .*/issue97-targettype-none/b/" > /dev/null dub-1.19.0/test/issue97-targettype-none/000077500000000000000000000000001360435400500177665ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none/.no_build000066400000000000000000000000001360435400500215500ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none/.no_run000066400000000000000000000000001360435400500212550ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none/a/000077500000000000000000000000001360435400500202065ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none/a/dub.sdl000066400000000000000000000000411360435400500214570ustar00rootroot00000000000000name "a" targetType "executable" dub-1.19.0/test/issue97-targettype-none/a/source/000077500000000000000000000000001360435400500215065ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none/a/source/app.d000066400000000000000000000001311360435400500224260ustar00rootroot00000000000000import std.stdio; void main() { writeln("Edit source/app.d to start your project."); } dub-1.19.0/test/issue97-targettype-none/b/000077500000000000000000000000001360435400500202075ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none/b/dub.sdl000066400000000000000000000000411360435400500214600ustar00rootroot00000000000000name "b" targetType "executable" dub-1.19.0/test/issue97-targettype-none/b/source/000077500000000000000000000000001360435400500215075ustar00rootroot00000000000000dub-1.19.0/test/issue97-targettype-none/b/source/app.d000066400000000000000000000001311360435400500224270ustar00rootroot00000000000000import std.stdio; void main() { writeln("Edit source/app.d to start your project."); } dub-1.19.0/test/issue97-targettype-none/dub.sdl000066400000000000000000000002731360435400500212460ustar00rootroot00000000000000name "issue97-targettype-none" targetType "none" dependency "issue97-targettype-none:a" version="*" dependency "issue97-targettype-none:b" version="*" subPackage "./a/" subPackage "./b/" dub-1.19.0/test/issue990-download-optional-selected.sh000077500000000000000000000003251360435400500225020ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue990-download-optional-selected rm -rf b/.dub ${DUB} remove gitcompatibledubpackage -n --version=* 2>/dev/null || true ${DUB} run dub-1.19.0/test/issue990-download-optional-selected/000077500000000000000000000000001360435400500221435ustar00rootroot00000000000000dub-1.19.0/test/issue990-download-optional-selected/.no_build000066400000000000000000000000001360435400500237250ustar00rootroot00000000000000dub-1.19.0/test/issue990-download-optional-selected/dub.sdl000066400000000000000000000001141360435400500234150ustar00rootroot00000000000000name "b" dependency "gitcompatibledubpackage" version="1.0.2" optional=true dub-1.19.0/test/issue990-download-optional-selected/dub.selections.json000066400000000000000000000001161360435400500257550ustar00rootroot00000000000000{ "fileVersion": 1, "versions": { "gitcompatibledubpackage": "1.0.2" } } dub-1.19.0/test/issue990-download-optional-selected/source/000077500000000000000000000000001360435400500234435ustar00rootroot00000000000000dub-1.19.0/test/issue990-download-optional-selected/source/app.d000066400000000000000000000001341360435400500243660ustar00rootroot00000000000000import gitcompatibledubpackage.subdir.file; void main() { assert(!hasTheWorldExploded); } dub-1.19.0/test/path-subpackage-ref/000077500000000000000000000000001360435400500171445ustar00rootroot00000000000000dub-1.19.0/test/path-subpackage-ref/dub.json000066400000000000000000000001441360435400500206100ustar00rootroot00000000000000{ "name": "test", "dependencies": { "test:subpack": "*" }, "subPackages": [ "subpack/" ] } dub-1.19.0/test/path-subpackage-ref/source/000077500000000000000000000000001360435400500204445ustar00rootroot00000000000000dub-1.19.0/test/path-subpackage-ref/source/app.d000066400000000000000000000000651360435400500213720ustar00rootroot00000000000000module app; import lib; void main() { libFunc(); } dub-1.19.0/test/path-subpackage-ref/subpack/000077500000000000000000000000001360435400500205745ustar00rootroot00000000000000dub-1.19.0/test/path-subpackage-ref/subpack/dub.json000066400000000000000000000002371360435400500222430ustar00rootroot00000000000000{ "name": "subpack", "description": "A minimal D application.", "copyright": "Copyright © 2014, sludwig", "authors": ["sludwig"], "dependencies": { } } dub-1.19.0/test/path-subpackage-ref/subpack/source/000077500000000000000000000000001360435400500220745ustar00rootroot00000000000000dub-1.19.0/test/path-subpackage-ref/subpack/source/lib.d000066400000000000000000000001141360435400500230030ustar00rootroot00000000000000import std.stdio; void libFunc() { writeln("Library function called."); } dub-1.19.0/test/pr1549-dub-exe-var.sh000077500000000000000000000004421360435400500167530ustar00rootroot00000000000000#! /usr/bin/env bash set -e . $(dirname "${BASH_SOURCE[0]}")/common.sh PR1549=$CURR_DIR/pr1549-dub-exe-var ${DUB} build --root ${PR1549} OUTPUT=$(${PR1549}/test-application) if [[ "$OUTPUT" != "modified code" ]]; then die "\$DUB build variable was (likely) not evaluated correctly"; fi dub-1.19.0/test/pr1549-dub-exe-var/000077500000000000000000000000001360435400500164145ustar00rootroot00000000000000dub-1.19.0/test/pr1549-dub-exe-var/.gitignore000066400000000000000000000000221360435400500203760ustar00rootroot00000000000000setmsg setmsg.exe dub-1.19.0/test/pr1549-dub-exe-var/.no_build000066400000000000000000000000001360435400500201760ustar00rootroot00000000000000dub-1.19.0/test/pr1549-dub-exe-var/dub.sdl000066400000000000000000000003231360435400500176700ustar00rootroot00000000000000name "test-application" targetType "executable" preBuildCommands "$DUB run --single $PACKAGE_DIR/setmsg.d -- \"modified code\"" postBuildCommands "$DUB run --single $PACKAGE_DIR/setmsg.d -- \"unmodified code\"" dub-1.19.0/test/pr1549-dub-exe-var/setmsg.d000066400000000000000000000007201360435400500200620ustar00rootroot00000000000000/+ dub.sdl: +/ import std.exception; import std.path; import std.process; import std.stdio; void main(in string[] args) { enforce(args.length > 1); const string msg = args[1]; const path = buildPath(environment["DUB_PACKAGE_DIR"], "source", "app.d"); auto file = File(path, "w"); file.writeln(`import std.stdio;`); file.writeln(); file.writeln(`void main() {`); file.writefln(` writeln("%s");`, msg); file.writeln(`}`); } dub-1.19.0/test/pr1549-dub-exe-var/source/000077500000000000000000000000001360435400500177145ustar00rootroot00000000000000dub-1.19.0/test/pr1549-dub-exe-var/source/app.d000066400000000000000000000001031360435400500206330ustar00rootroot00000000000000import std.stdio; void main() { writeln("unmodified code"); } dub-1.19.0/test/run-unittest.sh000077500000000000000000000051211360435400500163520ustar00rootroot00000000000000#!/usr/bin/env bash set -ueo pipefail . $(dirname "${BASH_SOURCE[0]}")/common.sh > $(dirname "${BASH_SOURCE[0]}")/test.log function log() { echo -e "\033[0;33m[INFO] $@\033[0m" echo "[INFO] $@" >> $(dirname "${BASH_SOURCE[0]}")/test.log } function logError() { echo -e 1>&2 "\033[0;31m[ERROR] $@\033[0m" echo "[ERROR] $@" >> $(dirname "${BASH_SOURCE[0]}")/test.log any_errors=1 } function die() { logError "$@" exit 1 } export -f log export -f die if [ -z ${DUB:-} ]; then die 'Variable $DUB must be defined to run the tests.' fi if [ -z ${DC:-} ]; then log '$DC not defined, assuming dmd...' DC=dmd fi DC_BIN=$(basename "$DC") CURR_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) FRONTEND="${FRONTEND:-}" if [ "$#" -gt 0 ]; then FILTER=$1; else FILTER=".*"; fi for script in $(ls $CURR_DIR/*.sh); do if [[ ! "$script" =~ $FILTER ]]; then continue; fi if [ "$script" = "$(readlink -f ${BASH_SOURCE[0]})" ] || [ "$(basename $script)" = "common.sh" ]; then continue; fi if [ -e $script.min_frontend ] && [ ! -z "$FRONTEND" ] && [ ${FRONTEND} \< $(cat $script.min_frontend) ]; then continue; fi log "Running $script..." DUB=$DUB DC=$DC CURR_DIR="$CURR_DIR" $script || logError "Script failure." done for pack in $(ls -d $CURR_DIR/*/); do if [[ ! "$pack" =~ $FILTER ]]; then continue; fi if [ -e $pack/.min_frontend ] && [ ! -z "$FRONTEND" -a "$FRONTEND" \< $(cat $pack/.min_frontend) ]; then continue; fi # First we build the packages if [ ! -e $pack/.no_build ] && [ ! -e $pack/.no_build_$DC_BIN ]; then # For sourceLibrary build=1 if [ -e $pack/.fail_build ]; then log "Building $pack, expected failure..." $DUB build --force --root=$pack --compiler=$DC 2>/dev/null && logError "Error: Failure expected, but build passed." else log "Building $pack..." $DUB build --force --root=$pack --compiler=$DC || logError "Build failure." fi else build=0 fi # We run the ones that are supposed to be run if [ $build -eq 1 ] && [ ! -e $pack/.no_run ] && [ ! -e $pack/.no_run_$DC_BIN ]; then log "Running $pack..." $DUB run --force --root=$pack --compiler=$DC || logError "Run failure." fi # Finally, the unittest part if [ $build -eq 1 ] && [ ! -e $pack/.no_test ] && [ ! -e $pack/.no_test_$DC_BIN ]; then log "Testing $pack..." $DUB test --force --root=$pack --compiler=$DC || logError "Test failure." fi done echo echo 'Testing summary:' cat $(dirname "${BASH_SOURCE[0]}")/test.log exit ${any_errors:-0} dub-1.19.0/test/sdl-package-simple/000077500000000000000000000000001360435400500167755ustar00rootroot00000000000000dub-1.19.0/test/sdl-package-simple/dub.sdl000066400000000000000000000000551360435400500202530ustar00rootroot00000000000000name "exec-simple"; targetType "executable"; dub-1.19.0/test/sdl-package-simple/source/000077500000000000000000000000001360435400500202755ustar00rootroot00000000000000dub-1.19.0/test/sdl-package-simple/source/app.d000066400000000000000000000000761360435400500212250ustar00rootroot00000000000000import std.stdio; void main() { writeln(__FUNCTION__); } dub-1.19.0/test/single-file-sdl-default-name.d000066400000000000000000000002251360435400500210150ustar00rootroot00000000000000/++dub.sdl: dependency "sourcelib-simple" path="1-sourceLib-simple" +/ module single; void main(string[] args) { import sourcelib.app; entry(); } dub-1.19.0/test/single-file-sdl-default-name.sh000077500000000000000000000004701360435400500212110ustar00rootroot00000000000000#!/usr/bin/env bash set -e cd ${CURR_DIR} rm -f single-file-sdl-default-name ${DUB} run --single single-file-sdl-default-name.d --compiler=${DC} if [ ! -f single-file-sdl-default-name ]; then echo "Normal invocation did not produce a binary in the current directory" exit 1 fi rm single-file-sdl-default-name dub-1.19.0/test/subpackage-common-with-sourcefile-globbing.sh000077500000000000000000000003471360435400500241610ustar00rootroot00000000000000#!/bin/sh set -e cd ${CURR_DIR}/subpackage-common-with-sourcefile-globbing rm -rf .dub dub.selections.json ${DUB} build --compiler=${DC} :server -v ${DUB} build --compiler=${DC} :client -v ${DUB} build --compiler=${DC} :common -v dub-1.19.0/test/subpackage-common-with-sourcefile-globbing/000077500000000000000000000000001360435400500236165ustar00rootroot00000000000000dub-1.19.0/test/subpackage-common-with-sourcefile-globbing/.no_build000066400000000000000000000000001360435400500254000ustar00rootroot00000000000000dub-1.19.0/test/subpackage-common-with-sourcefile-globbing/code/000077500000000000000000000000001360435400500245305ustar00rootroot00000000000000dub-1.19.0/test/subpackage-common-with-sourcefile-globbing/code/mypackage/000077500000000000000000000000001360435400500264715ustar00rootroot00000000000000dub-1.19.0/test/subpackage-common-with-sourcefile-globbing/code/mypackage/client/000077500000000000000000000000001360435400500277475ustar00rootroot00000000000000dub-1.19.0/test/subpackage-common-with-sourcefile-globbing/code/mypackage/client/app.d000066400000000000000000000001341360435400500306720ustar00rootroot00000000000000import mypackage.client.extra; import mypackage.common.blah; void main() { foo(); blah(); } dub-1.19.0/test/subpackage-common-with-sourcefile-globbing/code/mypackage/client/extra.d000066400000000000000000000000551360435400500312370ustar00rootroot00000000000000module mypackage.client.extra; void foo() {} dub-1.19.0/test/subpackage-common-with-sourcefile-globbing/code/mypackage/common/000077500000000000000000000000001360435400500277615ustar00rootroot00000000000000dub-1.19.0/test/subpackage-common-with-sourcefile-globbing/code/mypackage/common/blah.d000066400000000000000000000000551360435400500310340ustar00rootroot00000000000000module mypackage.common.blah; void blah() {} dub-1.19.0/test/subpackage-common-with-sourcefile-globbing/code/mypackage/server/000077500000000000000000000000001360435400500277775ustar00rootroot00000000000000dub-1.19.0/test/subpackage-common-with-sourcefile-globbing/code/mypackage/server/app.d000066400000000000000000000001341360435400500307220ustar00rootroot00000000000000import mypackage.server.extra; import mypackage.common.blah; void main() { foo(); blah(); } dub-1.19.0/test/subpackage-common-with-sourcefile-globbing/code/mypackage/server/extra.d000066400000000000000000000000551360435400500312670ustar00rootroot00000000000000module mypackage.server.extra; void foo() {} dub-1.19.0/test/subpackage-common-with-sourcefile-globbing/dub.sdl000066400000000000000000000006021360435400500250720ustar00rootroot00000000000000name "mypackage" targetType "none" subPackage { name "server" sourceFiles "code/mypackage/[sc][oe]*/*.d" targetType "executable" } subPackage { name "client" sourceFiles "code/mypackage/client/*.d" targetType "executable" dependency "mypackage:common" version="*" } subPackage { name "common" sourceFiles "code/mypackage/common/*.d" importPaths "code" targetType "library" } dub-1.19.0/test/subpackage-ref/000077500000000000000000000000001360435400500162125ustar00rootroot00000000000000dub-1.19.0/test/subpackage-ref/dub.json000066400000000000000000000001641360435400500176600ustar00rootroot00000000000000{ "name": "test", "dependencies": { "test:subpack": "*" }, "subPackages": [ { "name": "subpack" } ] } dub-1.19.0/test/subpackage-ref/source/000077500000000000000000000000001360435400500175125ustar00rootroot00000000000000dub-1.19.0/test/subpackage-ref/source/app.d000066400000000000000000000001311360435400500204320ustar00rootroot00000000000000import std.stdio; void main() { writeln("Edit source/app.d to start your project."); } dub-1.19.0/test/test-version-opt.sh000077500000000000000000000001501360435400500171300ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh $DUB --version | grep -qF 'DUB version' dub-1.19.0/test/test_registry.d000077500000000000000000000035661360435400500164240ustar00rootroot00000000000000#!/usr/bin/env dub /+dub.sdl: dependency "vibe-d" version="~>0.8.5" versions "VibeNoSSL" +/ import vibe.d; /* Provide a special API File Handler as Vibe.d's builtin serveStaticFiles doesn't deal well with query params. This will blindly check if the requestURI payload exists on the filesystem and if so, return the file. It replaces `?` with `__` for Windows compatibility. Params: skip = initial part of the requestURI to skip over folder = the base directory from which to serve API requests from */ auto apiFileHandler(string skip, string folder) { import std.functional : toDelegate; void handler(HTTPServerRequest req, HTTPServerResponse res) { import std.algorithm : skipOver; import std.path : buildPath; import std.file : exists; // ? can't be part of path names on Windows auto requestURI = req.requestURI.replace("?", "__"); requestURI.skipOver(skip); const reqFile = buildPath(folder, requestURI); if (reqFile.exists) { return req.sendFile(res, PosixPath(reqFile)); } } return toDelegate(&handler); } void main(string[] args) { import std.conv; immutable folder = readRequiredOption!string("folder", "Folder to service files from."); immutable port = readRequiredOption!uint("port", "Port to use"); auto router = new URLRouter; router.get("stop", (HTTPServerRequest req, HTTPServerResponse res){ res.writeVoidBody; exitEventLoop(); }); router.get("/packages/gitcompatibledubpackage/1.0.2.zip", (req, res) { res.writeBody("", HTTPStatus.badGateway); }); router.get("*", folder.serveStaticFiles); router.get("/fallback/*", folder.serveStaticFiles(new HTTPFileServerSettings("/fallback"))); router.get("/api/*", apiFileHandler("/", folder)); router.get("/fallback/api/*", apiFileHandler("/fallback/", folder)); listenHTTP(text(":", port), router); runApplication(); } dub-1.19.0/test/timeout.sh000077500000000000000000000024501360435400500153610ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh PORT=$(($$ + 1024)) # PID + 1024 log ' Testing unconnectable registry' if timeout 1s $DUB fetch dub --skip-registry=all --registry=http://localhost:$PORT; then die 'Fetching from unconnectable registry should fail.' elif [ $? -eq 124 ]; then die 'Fetching from unconnectable registry should fail immediately.' fi log ' Testing non-responding registry' cat | nc -l $PORT >/dev/null & PID=$! if timeout 10s $DUB fetch dub --skip-registry=all --registry=http://localhost:$PORT; then die 'Fetching from non-responding registry should fail.' elif [ $? -eq 124 ]; then die 'Fetching from non-responding registry should time-out within 8s.' fi kill $PID 2>/dev/null || true log ' Testing too slow registry' { res=$(printf 'HTTP/1.1 200 OK\r Server: dummy\r Content-Type: application/json\r Content-Length: 2\r \r {}') for i in $(seq 0 $((${#res} - 1))); do echo -n "${res:$i:1}" sleep 1 done } | nc -l $PORT >/dev/null & PID=$! if timeout 10s time $DUB fetch dub --skip-registry=all --registry=http://localhost:$PORT; then die 'Fetching from too slow registry should fail.' elif [ $? -eq 124 ]; then die 'Fetching from too slow registry should time-out within 8s.' fi kill $PID 2>/dev/null || true dub-1.19.0/test/version-filters-diamond/000077500000000000000000000000001360435400500200775ustar00rootroot00000000000000dub-1.19.0/test/version-filters-diamond/.gitignore000066400000000000000000000005341360435400500220710ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ issue1262-version-inheritance-diamond issue1262-version-inheritance-diamond.so issue1262-version-inheritance-diamond.dylib issue1262-version-inheritance-diamond.dll issue1262-version-inheritance-diamond.a issue1262-version-inheritance-diamond.lib issue1262-version-inheritance-diamond-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/version-filters-diamond/.no_build000066400000000000000000000000001360435400500216610ustar00rootroot00000000000000dub-1.19.0/test/version-filters-diamond/.no_run000066400000000000000000000000001360435400500213660ustar00rootroot00000000000000dub-1.19.0/test/version-filters-diamond/.no_test000066400000000000000000000000001360435400500215410ustar00rootroot00000000000000dub-1.19.0/test/version-filters-diamond/daughter/000077500000000000000000000000001360435400500217025ustar00rootroot00000000000000dub-1.19.0/test/version-filters-diamond/daughter/.gitignore000066400000000000000000000002101360435400500236630ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ daughter.so daughter.dylib daughter.dll daughter.a daughter.lib daughter-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/version-filters-diamond/daughter/dub.sdl000066400000000000000000000002661360435400500231640ustar00rootroot00000000000000name "daughter" versions "Daughter" debugVersions "dDaughter" x:versionFilters "Daughter" "Parent" x:debugVersionFilters "dDaughter" "dParent" dependency "diamond" path="../diamond" dub-1.19.0/test/version-filters-diamond/daughter/source/000077500000000000000000000000001360435400500232025ustar00rootroot00000000000000dub-1.19.0/test/version-filters-diamond/daughter/source/dummy.d000066400000000000000000000016101360435400500245000ustar00rootroot00000000000000module daughter.dummy; version (Parent) {} else static assert(0, "Expected Parent to be set"); // via dependency version (Daughter) {} else static assert(0, "Expected Daughter to be set"); // local version (Son) static assert(0, "Expected Son to not be set"); version (Diamond) static assert(0, "Expected Diamond to not be set"); debug (dParent) {} else static assert(0, "Expected dParent to be set"); // via dependency debug (dDaughter) {} else static assert(0, "Expected dDaughter to be set"); // local debug (dSon) {} else static assert(0, "Expected dSon to be set"); // via diamond dependency debug (dDiamond) static assert(0, "Expected dDiamond to not be set"); version (Have_daughter) static assert(0, "Expected Have_daughter to not be set"); version (Have_son) static assert(0, "Expected Have_son to not be set"); version (Have_diamond) static assert(0, "Expected Have_diamond to not be set"); dub-1.19.0/test/version-filters-diamond/diamond/000077500000000000000000000000001360435400500215125ustar00rootroot00000000000000dub-1.19.0/test/version-filters-diamond/diamond/.gitignore000066400000000000000000000002021360435400500234740ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ diamond.so diamond.dylib diamond.dll diamond.a diamond.lib diamond-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/version-filters-diamond/diamond/dub.sdl000066400000000000000000000000731360435400500227700ustar00rootroot00000000000000name "diamond" versions "Diamond" debugVersions "dDiamond" dub-1.19.0/test/version-filters-diamond/diamond/source/000077500000000000000000000000001360435400500230125ustar00rootroot00000000000000dub-1.19.0/test/version-filters-diamond/diamond/source/dummy.d000066400000000000000000000015461360435400500243200ustar00rootroot00000000000000module diamond.dummy; template hasVersion(string v) { mixin("version ("~v~") enum hasVersion = true; else enum hasVersion = false;"); } template hasDebugVersion(string v) { mixin("debug ("~v~") enum hasDebugVersion = true; else enum hasDebugVersion = false;"); } // checking inference here version (Parent) {} else static assert(0, "Expected Parent to be set"); version (Daughter) {} else static assert(0, "Expected Daughter to be set"); static assert(!hasVersion!"Son"); static assert(!hasVersion!"Diamond"); debug (dParent) {} else static assert(0, "Expected dParent to be set"); static assert(!hasDebugVersion!"dDaughter"); debug (dSon) {} else static assert(0, "Expected dSon to be set"); static assert(!hasDebugVersion!"dDiamond"); static assert(!hasVersion!"Have_daughter"); static assert(!hasVersion!"Have_son"); static assert(!hasVersion!"Have_diamond"); dub-1.19.0/test/version-filters-diamond/dub.sdl000066400000000000000000000003051360435400500213530ustar00rootroot00000000000000name "version-filters-diamond" versions "Parent" debugVersions "dParent" x:versionFilters "Parent" x:debugVersionFilters "dParent" dependency "daughter" path="daughter" dependency "son" path="son" dub-1.19.0/test/version-filters-diamond/son/000077500000000000000000000000001360435400500206765ustar00rootroot00000000000000dub-1.19.0/test/version-filters-diamond/son/.gitignore000066400000000000000000000001521360435400500226640ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ son.so son.dylib son.dll son.a son.lib son-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/version-filters-diamond/son/dub.sdl000066400000000000000000000002121360435400500221470ustar00rootroot00000000000000name "son" versions "Son" debugVersions "dSon" x:versionFilters "Son" x:debugVersionFilters "dSon" dependency "diamond" path="../diamond" dub-1.19.0/test/version-filters-diamond/son/source/000077500000000000000000000000001360435400500221765ustar00rootroot00000000000000dub-1.19.0/test/version-filters-diamond/son/source/dummy.d000066400000000000000000000016411360435400500235000ustar00rootroot00000000000000module son.dummy; version (Parent) {} else static assert(0, "Expected Parent to be set"); // via dependency version (Daughter) {} else static assert(0, "Expected Daughter to not be set"); // via diamond dependency version (Son) {} else static assert(0, "Expected Son to be set"); // local version (Diamond) static assert(0, "Expected Diamond to not be set"); debug (dParent) {} else static assert(0, "Expected dParent to be set"); // via dependency debug (dDaughter) static assert(0, "Expected dDaughter to not be set"); // via diamond dependency debug (dSon) {} else static assert(0, "Expected dSon to be set"); // local debug (dDiamond) static assert(0, "Expected dDiamond to not be set"); version (Have_daughter) static assert(0, "Expected Have_daughter to not be set"); version (Have_son) static assert(0, "Expected Have_son to not be set"); version (Have_diamond) static assert(0, "Expected Have_diamond to not be set"); dub-1.19.0/test/version-filters-diamond/source/000077500000000000000000000000001360435400500213775ustar00rootroot00000000000000dub-1.19.0/test/version-filters-diamond/source/app.d000066400000000000000000000017171360435400500223320ustar00rootroot00000000000000version (Parent) {} else static assert(0, "Expected Parent to be set"); // local version (Daughter) {} else static assert(0, "Expected Daughter to not be set"); // via dependency version (Son) {} else static assert(0, "Expected Son to not be set"); // via dependency version (Diamond) static assert(0, "Expected Diamond to not be set"); // unused by dependencies debug (dParent) {} else static assert(0, "Expected dParent to be set"); // local debug (dDaughter) {} else static assert(0, "Expected dDaughter to be set"); // via dependency debug (dSon) {} else static assert(0, "Expected dSon to not be set"); // via dependency debug (dDiamond) static assert(0, "Expected dDiamond to not be set"); // unused by dependencies version (Have_daugther) static assert(0, "Expected Have_daugther to not be set"); version (Have_son) static assert(0, "Expected Have_son to not be set"); version (Have_diamond) static assert(0, "Expected Have_diamond to not be set"); void main() { } dub-1.19.0/test/version-filters-none/000077500000000000000000000000001360435400500174235ustar00rootroot00000000000000dub-1.19.0/test/version-filters-none/.gitignore000066400000000000000000000005341360435400500214150ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ issue1262-version-inheritance-diamond issue1262-version-inheritance-diamond.so issue1262-version-inheritance-diamond.dylib issue1262-version-inheritance-diamond.dll issue1262-version-inheritance-diamond.a issue1262-version-inheritance-diamond.lib issue1262-version-inheritance-diamond-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/version-filters-none/.no_build000066400000000000000000000000001360435400500212050ustar00rootroot00000000000000dub-1.19.0/test/version-filters-none/.no_run000066400000000000000000000000001360435400500207120ustar00rootroot00000000000000dub-1.19.0/test/version-filters-none/.no_test000066400000000000000000000000001360435400500210650ustar00rootroot00000000000000dub-1.19.0/test/version-filters-none/dub.sdl000066400000000000000000000001361360435400500207010ustar00rootroot00000000000000name "version-filters-none" versions "Parent" debugVersions "dParent" x:versionFilters "none" dub-1.19.0/test/version-filters-none/source/000077500000000000000000000000001360435400500207235ustar00rootroot00000000000000dub-1.19.0/test/version-filters-none/source/app.d000066400000000000000000000002311360435400500216440ustar00rootroot00000000000000version (Parent) static assert(0, "Expected Parent to not be set"); debug (dParent) static assert(0, "Expected dParent to not be set"); void main() { } dub-1.19.0/test/version-filters-source-dep/000077500000000000000000000000001360435400500205325ustar00rootroot00000000000000dub-1.19.0/test/version-filters-source-dep/.gitignore000066400000000000000000000005341360435400500225240ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ issue1262-version-inheritance-diamond issue1262-version-inheritance-diamond.so issue1262-version-inheritance-diamond.dylib issue1262-version-inheritance-diamond.dll issue1262-version-inheritance-diamond.a issue1262-version-inheritance-diamond.lib issue1262-version-inheritance-diamond-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/version-filters-source-dep/.no_build000066400000000000000000000000001360435400500223140ustar00rootroot00000000000000dub-1.19.0/test/version-filters-source-dep/.no_run000066400000000000000000000000001360435400500220210ustar00rootroot00000000000000dub-1.19.0/test/version-filters-source-dep/.no_test000066400000000000000000000000001360435400500221740ustar00rootroot00000000000000dub-1.19.0/test/version-filters-source-dep/dub.sdl000066400000000000000000000002161360435400500220070ustar00rootroot00000000000000name "version-filters-source-dep" versions "Parent" debugVersions "dParent" x:versionFilters "none" dependency "source-dep" path="source-dep" dub-1.19.0/test/version-filters-source-dep/source-dep/000077500000000000000000000000001360435400500226005ustar00rootroot00000000000000dub-1.19.0/test/version-filters-source-dep/source-dep/dub.sdl000066400000000000000000000003241360435400500240550ustar00rootroot00000000000000name "source-dep" versions "SourceDep" debugVersions "dSourceDep" # filter of sourceOnly libs are merged with dependents x:versionFilters "SourceDep" x:debugVersionFilters "dSourceDep" targetType "sourceLibrary" dub-1.19.0/test/version-filters-source-dep/source-dep/source/000077500000000000000000000000001360435400500241005ustar00rootroot00000000000000dub-1.19.0/test/version-filters-source-dep/source-dep/source/dummy.d000066400000000000000000000004761360435400500254070ustar00rootroot00000000000000module sourcedep.dummy; version (Parent) static assert(0, "Expected Parent to not be set"); version (SourceDep) {} else static assert(0, "Expected SourceDep to be set"); debug (dParent) static assert(0, "Expected dParent to not be set"); debug (dSourceDep) {} else static assert(0, "Expected dSourceDep to be set"); dub-1.19.0/test/version-filters-source-dep/source/000077500000000000000000000000001360435400500220325ustar00rootroot00000000000000dub-1.19.0/test/version-filters-source-dep/source/app.d000066400000000000000000000004661360435400500227650ustar00rootroot00000000000000version (Parent) static assert(0, "Expected Parent to not be set"); version (SourceDep) {} else static assert(0, "Expected SourceDep to be set"); debug (dParent) static assert(0, "Expected dParent to not be set"); debug (dSourceDep) {} else static assert(0, "Expected dSourceDep to be set"); void main() { } dub-1.19.0/test/version-filters.sh000077500000000000000000000005311360435400500170240ustar00rootroot00000000000000#!/usr/bin/env bash . $(dirname "${BASH_SOURCE[0]}")/common.sh $DUB build --root="$CURR_DIR/version-filters" --filter-versions $DUB build --root="$CURR_DIR/version-filters-diamond" --filter-versions $DUB build --root="$CURR_DIR/version-filters-source-dep" --filter-versions $DUB build --root="$CURR_DIR/version-filters-none" --filter-versions dub-1.19.0/test/version-filters/000077500000000000000000000000001360435400500164665ustar00rootroot00000000000000dub-1.19.0/test/version-filters/.gitignore000066400000000000000000000005341360435400500204600ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ issue1262-version-inheritance-diamond issue1262-version-inheritance-diamond.so issue1262-version-inheritance-diamond.dylib issue1262-version-inheritance-diamond.dll issue1262-version-inheritance-diamond.a issue1262-version-inheritance-diamond.lib issue1262-version-inheritance-diamond-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/version-filters/.no_build000066400000000000000000000000001360435400500202500ustar00rootroot00000000000000dub-1.19.0/test/version-filters/.no_run000066400000000000000000000000001360435400500177550ustar00rootroot00000000000000dub-1.19.0/test/version-filters/.no_test000066400000000000000000000000001360435400500201300ustar00rootroot00000000000000dub-1.19.0/test/version-filters/daughter/000077500000000000000000000000001360435400500202715ustar00rootroot00000000000000dub-1.19.0/test/version-filters/daughter/.gitignore000066400000000000000000000002101360435400500222520ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ daughter.so daughter.dylib daughter.dll daughter.a daughter.lib daughter-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/version-filters/daughter/dub.sdl000066400000000000000000000002171360435400500215470ustar00rootroot00000000000000name "daughter" versions "Daughter" debugVersions "dDaughter" x:versionFilters "Daughter" "Parent" x:debugVersionFilters "dDaughter" "dParent" dub-1.19.0/test/version-filters/daughter/source/000077500000000000000000000000001360435400500215715ustar00rootroot00000000000000dub-1.19.0/test/version-filters/daughter/source/dummy.d000066400000000000000000000011301360435400500230640ustar00rootroot00000000000000module daughter.dummy; version (Parent) {} else static assert(0, "Expected Parent to be set"); version (Daughter) {} else static assert(0, "Expected Daughter to be set"); version (Son) static assert(0, "Expected Son to not be set"); debug (dParent) {} else static assert(0, "Expected dParent to be set"); debug (dDaughter) {} else static assert(0, "Expected dDaughter to be set"); debug (dSon) static assert(0, "Expected dSon to not be set"); version (Have_daughter) static assert(0, "Expected Have_daughter to not be set"); version (Have_son) static assert(0, "Expected Have_son to not be set"); dub-1.19.0/test/version-filters/dub.sdl000066400000000000000000000002751360435400500177500ustar00rootroot00000000000000name "version-filters" versions "Parent" debugVersions "dParent" x:versionFilters "Parent" x:debugVersionFilters "dParent" dependency "daughter" path="daughter" dependency "son" path="son" dub-1.19.0/test/version-filters/son/000077500000000000000000000000001360435400500172655ustar00rootroot00000000000000dub-1.19.0/test/version-filters/son/.gitignore000066400000000000000000000001521360435400500212530ustar00rootroot00000000000000.dub docs.json __dummy.html docs/ son.so son.dylib son.dll son.a son.lib son-test-* *.exe *.o *.obj *.lst dub-1.19.0/test/version-filters/son/dub.sdl000066400000000000000000000001431360435400500205410ustar00rootroot00000000000000name "son" versions "Son" debugVersions "dSon" x:versionFilters "Son" x:debugVersionFilters "dSon" dub-1.19.0/test/version-filters/son/source/000077500000000000000000000000001360435400500205655ustar00rootroot00000000000000dub-1.19.0/test/version-filters/son/source/dummy.d000066400000000000000000000011131360435400500220610ustar00rootroot00000000000000module son.dummy; version (Parent) static assert(0, "Expected Parent to not be set"); version (Daughter) static assert(0, "Expected Daughter to not be set"); version (Son) {} else static assert(0, "Expected Son to be set"); debug (dParent) static assert(0, "Expected dParent to not be set"); debug (dDaughter) static assert(0, "Expected dDaughter to not be set"); debug (dSon) {} else static assert(0, "Expected dSon to be set"); version (Have_daughter) static assert(0, "Expected Have_daughter to not be set"); version (Have_son) static assert(0, "Expected Have_son to not be set"); dub-1.19.0/test/version-filters/source/000077500000000000000000000000001360435400500177665ustar00rootroot00000000000000dub-1.19.0/test/version-filters/source/app.d000066400000000000000000000012631360435400500207150ustar00rootroot00000000000000version (Parent) {} else static assert(0, "Expected Parent to be set"); // local version (Daughter) {} else static assert(0, "Expected Daughter to be set"); // via dependency version (Son) {} else static assert(0, "Expected Son to be set"); // via dependency debug (dParent) {} else static assert(0, "Expected dParent to be set"); // local debug (dDaughter) {} else static assert(0, "Expected dDaughter to be set"); // via dependency debug (dSon) {} else static assert(0, "Expected dSon to be set"); // via dependency version (Have_daugther) static assert(0, "Expected Have_daugther to not be set"); version (Have_son) static assert(0, "Expected Have_son to not be set"); void main() { } dub-1.19.0/travis-ci.sh000077500000000000000000000034151360435400500146170ustar00rootroot00000000000000#!/bin/bash set -v -e -o pipefail source ~/dlang/*/activate # activate host compiler if [ -z "$FRONTEND" -o "$FRONTEND" \> 2.074.z ]; then vibe_ver=$(jq -r '.versions | .["vibe-d"]' < dub.selections.json) dub fetch vibe-d --version=$vibe_ver # get optional dependency dub test --compiler=${DC} -c library-nonet fi if [ "$FRONTEND" \> 2.087.z ]; then DFLAGS='-preview=dip1000 -w -g -debug' DMD="$(command -v $DMD)" ./build.sh fi function clean() { # Hard reset of the DUB local folder is necessary as some tests # currently don't properly clean themselves rm -rf ~/.dub git clean -dxf -- test } if [ "$COVERAGE" = true ]; then # library-nonet fails to build with coverage (Issue 13742) dub test --compiler=${DC} -b unittest-cov ./build.sh -cov # run tests with different compilers DUB=`pwd`/bin/dub DC=${DC} test/run-unittest.sh deactivate clean export FRONTEND=2.077 source $(~/dlang/install.sh ldc-1.7.0 --activate) DUB=`pwd`/bin/dub DC=${DC} test/run-unittest.sh deactivate clean export FRONTEND=2.068 source $(~/dlang/install.sh gdc-4.8.5 --activate) DUB=`pwd`/bin/dub DC=${DC} test/run-unittest.sh deactivate else ./build.sh DUB=`pwd`/bin/dub DC=${DC} test/run-unittest.sh fi if [ "$COVERAGE" = true ]; then wget https://codecov.io/bash -O codecov.sh bash codecov.sh fi # check for trailing whitespace (needs to be done only once per build) if [ "$COVERAGE" = true ]; then find . -type f -name '*.d' -exec grep -Hn "[[:blank:]]$" {} \; fi # check that the man page generation still works (only once) if [ "$COVERAGE" = true ]; then source $(~/dlang/install.sh dmd --activate) source $(~/dlang/install.sh dub --activate) dub --single -v scripts/man/gen_man.d fi