pax_global_header00006660000000000000000000000064126725731500014522gustar00rootroot0000000000000052 comment=764e68d92bfd7ca76e8df98d9fb96c2ec2b605d0 dub-0.9.24/000077500000000000000000000000001267257315000123705ustar00rootroot00000000000000dub-0.9.24/.editorconfig000066400000000000000000000002441267257315000150450ustar00rootroot00000000000000root = 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-0.9.24/.gitignore000066400000000000000000000011311267257315000143540ustar00rootroot00000000000000*.o *.obj .dub .directory dub.selections.json docs.json __dummy.html # Ignore build files. /bin/dub /bin/__test__library-nonet__ /bin/__test__library__ # Ignore files or directories created by the test suite. /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/describe-project/dummy.dat /test/describe-project/dummy-dep1.dat dub-0.9.24/.travis.yml000066400000000000000000000004721267257315000145040ustar00rootroot00000000000000language: d sudo: false matrix: include: - d: dmd-2.068.2-b1 - d: dmd-2.068.1 - d: dmd-2.067.1 env: - COVERAGE=true - d: dmd-2.066.1 - d: dmd-2.065.0 - d: dmd-2.064.2 - d: ldc-0.15.1 - d: ldc-0.14.0 - d: gdc-4.9.2 - d: gdc-4.9.0 script: - ./travis-ci.sh dub-0.9.24/CHANGELOG.md000066400000000000000000001361231267257315000142070ustar00rootroot00000000000000Changelog ========= v0.9.24 - 2015-09- -------------------- ### 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/D-Programming-Language/dub/issues/348 [issue393]: https://github.com/D-Programming-Language/dub/issues/393 [issue535]: https://github.com/D-Programming-Language/dub/issues/535 [issue540]: https://github.com/D-Programming-Language/dub/issues/540 [issue543]: https://github.com/D-Programming-Language/dub/issues/543 [issue546]: https://github.com/D-Programming-Language/dub/issues/546 [issue547]: https://github.com/D-Programming-Language/dub/issues/547 [issue552]: https://github.com/D-Programming-Language/dub/issues/552 [issue552]: https://github.com/D-Programming-Language/dub/issues/552 [issue553]: https://github.com/D-Programming-Language/dub/issues/553 [issue560]: https://github.com/D-Programming-Language/dub/issues/560 [issue561]: https://github.com/D-Programming-Language/dub/issues/561 [issue564]: https://github.com/D-Programming-Language/dub/issues/564 [issue565]: https://github.com/D-Programming-Language/dub/issues/565 [issue572]: https://github.com/D-Programming-Language/dub/issues/572 [issue574]: https://github.com/D-Programming-Language/dub/issues/574 [issue580]: https://github.com/D-Programming-Language/dub/issues/580 [issue581]: https://github.com/D-Programming-Language/dub/issues/581 [issue582]: https://github.com/D-Programming-Language/dub/issues/582 [issue585]: https://github.com/D-Programming-Language/dub/issues/585 [issue587]: https://github.com/D-Programming-Language/dub/issues/587 [issue592]: https://github.com/D-Programming-Language/dub/issues/592 [issue593]: https://github.com/D-Programming-Language/dub/issues/593 [issue596]: https://github.com/D-Programming-Language/dub/issues/596 [issue601]: https://github.com/D-Programming-Language/dub/issues/601 [issue613]: https://github.com/D-Programming-Language/dub/issues/613 [issue617]: https://github.com/D-Programming-Language/dub/issues/617 [issue621]: https://github.com/D-Programming-Language/dub/issues/621 [issue678]: https://github.com/D-Programming-Language/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 platfrom 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 speficied 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 prerelease 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 comipler 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, inculding 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 erroneos "-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 confised 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-0.9.24/LICENSE.txt000066400000000000000000000020561267257315000142160ustar00rootroot00000000000000Copyright (c) 2012-2013 RejectedSoftware e.K. 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-0.9.24/LICENSE_DE.txt000066400000000000000000000021351267257315000145640ustar00rootroot00000000000000Copyright (c) 2012-2013 RejectedSoftware e.K. Hiermit wird unentgeltlich, jeder Person, die eine Kopie der Software und der zugehrigen Dokumentationen (die "Software") erhlt, die Erlaubnis erteilt, uneingeschrnkt zu benutzen, inklusive und ohne Ausnahme, dem Recht, sie zu verwenden, kopieren, ndern, fusionieren, verlegen, verbreiten, unterlizenzieren und/oder zu verkaufen, und Personen, die diese Software erhalten, diese Rechte zu geben, unter den folgenden Bedingungen: Der obige Urheberrechtsvermerk und dieser Erlaubnisvermerk sind in allen Kopien oder Teilkopien der Software beizulegen. DIE SOFTWARE WIRD OHNE JEDE AUSDRCKLICHE ODER IMPLIZIERTE GARANTIE BEREITGESTELLT, EINSCHLIESSLICH DER GARANTIE ZUR BENUTZUNG FR DEN VORGESEHENEN ODER EINEM BESTIMMTEN ZWECK SOWIE JEGLICHER RECHTSVERLETZUNG, JEDOCH NICHT DARAUF BESCHRNKT. IN KEINEM FALL SIND DIE AUTOREN ODER COPYRIGHTINHABER FR JEGLICHEN SCHADEN ODER SONSTIGE ANSPRCHE HAFTBAR ZU MACHEN, OB INFOLGE DER ERFLLUNG EINES VERTRAGES, EINES DELIKTES ODER ANDERS IM ZUSAMMENHANG MIT DER SOFTWARE ODER SONSTIGER VERWENDUNG DER SOFTWARE ENTSTANDEN. dub-0.9.24/README.md000066400000000000000000000104321267257315000136470ustar00rootroot00000000000000# dub package manager [![Build Status](https://travis-ci.org/D-Programming-Language/dub.svg?branch=master)](https://travis-ci.org/D-Programming-Language/dub) [![Coverage Status](https://coveralls.io/repos/D-Programming-Language/dub/badge.svg)](https://coveralls.io/r/D-Programming-Language/dub) Package and build manager for [D](http://dlang.org/) applications and libraries. There is a central [package registry](https://github.com/D-Programming-Language/dub-registry/) located at . ## Introduction DUB emerged as a more general replacement for [vibe.d's](http://vibed.org/) package manager. It does not imply a dependecy 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 support the use of dub.json (dub's package description) as 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 maintainance 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` or `brew install dub --HEAD` to install the stable or the git HEAD version respectively. ### 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. ## 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/D-Programming-Language/dub/blob/master/source/dub/package_.d#L40). For examples on how to replicate the command line functionality, see [commandline.d](https://github.com/D-Programming-Language/dub/blob/master/source/dub/commandline.d). dub-0.9.24/bin/000077500000000000000000000000001267257315000131405ustar00rootroot00000000000000dub-0.9.24/bin/libcurl.dll000066400000000000000000012530001267257315000152720ustar00rootroot00000000000000MZ@ !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-0.9.24/bin/ssleay32.dll000066400000000000000000010060001267257315000152770ustar00rootroot00000000000000MZ@ !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 -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-0.9.24/build.cmd000066400000000000000000000010271267257315000141540ustar00rootroot00000000000000@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 -debug -w -version=DubUseCurl -Isource curl.lib %* @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-0.9.24/build.sh000077500000000000000000000024111267257315000140240ustar00rootroot00000000000000#!/bin/sh 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 # link against libcurl LIBS=`pkg-config --libs libcurl 2>/dev/null || echo "-lcurl"` # fix for modern GCC versions with --as-needed by default if [ "$DMD" = "dmd" ]; then if [ `uname` = "Linux" ]; then LIBS="-l:libphobos2.a $LIBS" else LIBS="-lphobos2 $LIBS" fi elif [ "$DMD" = "ldmd2" ]; then LIBS="-lphobos2-ldc $LIBS" fi # adjust linker flags for dmd 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 $DMD... $DMD -ofbin/dub -w -version=DubUseCurl -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-0.9.24/curl.lib000066400000000000000000000220001267257315000140170ustar00rootroot00000000000000 curl_easy_cleanup6_curl_easy_cleanup libcurl.dllcurl_easy_cleanupcurl_easy_duphandle:_curl_easy_duphandle libcurl.dllcurl_easy_duphandlecurl_easy_escape4_curl_easy_escape libcurl.dllcurl_easy_escapecurl_easy_getinfo6_curl_easy_getinfo libcurl.dllcurl_easy_getinfocurl_easy_init0_curl_easy_init libcurl.dllcurl_easy_initcurl_easy_pause2_curl_easy_pause libcurl.dllcurl_easy_pausecurl_easy_perform6_curl_easy_perform libcurl.dllcurl_easy_performcurl_easy_recv0_curl_easy_recv libcurl.dllcurl_easy_recvcurl_easy_reset2_curl_easy_reset libcurl.dllcurl_easy_resetcurl_easy_send0_curl_easy_send libcurl.dllcurl_easy_sendcurl_easy_setopt4_curl_easy_setopt libcurl.dllcurl_easy_setoptcurl_easy_strerror8_curl_easy_strerror libcurl.dllcurl_easy_strerrorcurl_easy_unescape8_curl_easy_unescape libcurl.dllcurl_easy_unescape curl_escape* _curl_escape libcurl.dll curl_escape curl_formadd, _curl_formadd libcurl.dll curl_formadd curl_formfree._curl_formfree libcurl.dll curl_formfree curl_formget, _curl_formget libcurl.dll curl_formget curl_free& _curl_free libcurl.dll curl_free curl_getdate, _curl_getdate libcurl.dll curl_getdate curl_getenv* _curl_getenv libcurl.dll curl_getenvcurl_global_cleanup:_curl_global_cleanup libcurl.dllcurl_global_cleanupcurl_global_init4_curl_global_init libcurl.dllcurl_global_initcurl_global_init_mem<_curl_global_init_mem libcurl.dllcurl_global_init_mem curl_maprintf._curl_maprintf libcurl.dll curl_maprintf curl_mfprintf._curl_mfprintf libcurl.dll curl_mfprintf curl_mprintf, _curl_mprintf libcurl.dll curl_mprintfcurl_msnprintf0_curl_msnprintf libcurl.dllcurl_msnprintf curl_msprintf._curl_msprintf libcurl.dll curl_msprintfcurl_multi_add_handle>_curl_multi_add_handle libcurl.dllcurl_multi_add_handlecurl_multi_assign6_curl_multi_assign libcurl.dllcurl_multi_assigncurl_multi_cleanup8_curl_multi_cleanup libcurl.dllcurl_multi_cleanupcurl_multi_fdset4_curl_multi_fdset libcurl.dllcurl_multi_fdsetcurl_multi_info_read<_curl_multi_info_read libcurl.dllcurl_multi_info_readcurl_multi_init2_curl_multi_init libcurl.dllcurl_multi_initcurl_multi_perform8_curl_multi_perform libcurl.dllcurl_multi_performcurl_multi_remove_handleD_curl_multi_remove_handle libcurl.dllcurl_multi_remove_handlecurl_multi_setopt6_curl_multi_setopt libcurl.dllcurl_multi_setoptcurl_multi_socket6_curl_multi_socket libcurl.dllcurl_multi_socketcurl_multi_socket_actionD_curl_multi_socket_action libcurl.dllcurl_multi_socket_actioncurl_multi_socket_all>_curl_multi_socket_all libcurl.dllcurl_multi_socket_allcurl_multi_strerror:_curl_multi_strerror libcurl.dllcurl_multi_strerrorcurl_multi_timeout8_curl_multi_timeout libcurl.dllcurl_multi_timeoutcurl_multi_wait2_curl_multi_wait libcurl.dllcurl_multi_waitcurl_mvaprintf0_curl_mvaprintf libcurl.dllcurl_mvaprintfcurl_mvfprintf0_curl_mvfprintf libcurl.dllcurl_mvfprintf curl_mvprintf._curl_mvprintf libcurl.dll curl_mvprintfcurl_mvsnprintf2_curl_mvsnprintf libcurl.dllcurl_mvsnprintfcurl_mvsprintf0_curl_mvsprintf libcurl.dllcurl_mvsprintfcurl_share_cleanup8_curl_share_cleanup libcurl.dllcurl_share_cleanupcurl_share_init2_curl_share_init libcurl.dllcurl_share_initcurl_share_setopt6_curl_share_setopt libcurl.dllcurl_share_setoptcurl_share_strerror:_curl_share_strerror libcurl.dllcurl_share_strerrorcurl_slist_append6_curl_slist_append libcurl.dllcurl_slist_appendcurl_slist_free_all:_curl_slist_free_all libcurl.dllcurl_slist_free_all curl_strequal._curl_strequal libcurl.dll curl_strequalcurl_strnequal0_curl_strnequal libcurl.dllcurl_strnequal curl_unescape._curl_unescape libcurl.dll curl_unescape curl_version, _curl_version libcurl.dll curl_versioncurl_version_info6_curl_version_info libcurl.dllcurl_version_info@(TJ3fn]w_curl_easy_unescape!D_curl_formfree!T_curl_global_init!r_curl_multi_socket_all!_curl_mvsprintf!_curl_share_init!_curl_unescape!7_curl_easy_send3 _curl_getenvg_curl_maprintf~_curl_multi_info_read_curl_mvfprintf_curl_mvprintf_curl_share_cleanup _curl_version_infoALp:dC͛Y2)zĄ_curl_easy_duphandle!_curl_easy_recv!)_curl_formadd!O _curl_getenv!g_curl_maprintf!~_curl_mfprintf!_curl_multi_add_handle!_curl_multi_socket!_curl_multi_timeout!_curl_multi_wait!_curl_mvsnprintf!_curl_share_setopt!_curl_slist_free_all!'_curl_easy_duphandle_curl_easy_setopt8 _curl_free^_curl_global_init_memx_curl_msprintf_curl_multi_fdset_curl_strequal-J?V_5vk(_curl_easy_cleanup!_curl_easy_init!_curl_global_init_mem!x_curl_msnprintf!_curl_multi_setopt!_curl_multi_strerror!_curl_mvprintf!_curl_share_cleanup! _curl_easy_getinfo_curl_easy_recv) _curl_formaddO_curl_multi_cleanup_curl_multi_init_curl_multi_perform_curl_multi_socket_all_curl_share_init8]hqGQ){_curl_easy_escape! _curl_easy_getinfo!_curl_multi_remove_handle!_curl_multi_socket_action!_curl_mvaprintf!_curl_share_strerror!_curl_slist_append!!_curl_strequal!-_curl_strnequal!2_curl_version!< _curl_escapeJ_curl_mfprintf _curl_mprintf_curl_msnprintf_curl_multi_assign_curl_multi_remove_handle_curl_multi_socket_action_curl_mvaprintf_curl_mvsprintf3['Pypf_curl_mprintf!_curl_msprintf!_curl_multi_assign!_curl_multi_fdset!_curl_version_info!A_curl_easy_escape _curl_easy_init_curl_easy_pause_curl_easy_strerror> _curl_getdateb_curl_multi_strerror_curl_mvsnprintf_curl_share_setopt_curl_unescape7w(9LnX0c@_curl_easy_pause!_curl_easy_setopt!8 _curl_escape!J_curl_formget!Y _curl_free!^_curl_multi_cleanup!_curl_multi_perform!_curl_easy_cleanup_curl_easy_unescapeD_curl_formfreeT _curl_formgetY_curl_global_cleanupl_curl_global_initr_curl_multi_socket_curl_share_strerror_curl_slist_append!@_'TJi3v_curl_easy_perform!#_curl_getdate!b_curl_global_cleanup!l_curl_multi_info_read!_curl_multi_init!_curl_mvfprintf!_curl_easy_perform#_curl_easy_reset._curl_multi_add_handle_curl_multi_setopt_curl_multi_timeout_curl_multi_wait_curl_slist_free_all'_curl_strnequal2 _curl_version<dub-0.9.24/dub.json000066400000000000000000000015711267257315000140410ustar00rootroot00000000000000{ "name": "dub", "description": "Package manager for D packages", "license": "MIT", "copyright": "Copyright © 2012-2014 rejectedsoftware e.K., Copyright © 2012-2014 Matthias Dondorff", "authors": [ "Matthias Dondorff", "Sönke Ludwig" ], "targetPath": "bin", "configurations": [ { "name": "application", "targetType": "executable", "mainSourceFile": "source/app.d", "libs": ["curl"], "versions": ["DubUseCurl"] }, { "name": "library", "targetType": "library", "excludedSourceFiles": ["source/app.d"], "libs": ["curl"], "copyFiles-windows": ["bin/libcurl.dll", "bin/libeay32.dll", "bin/ssleay32.dll"], "versions": ["DubUseCurl"] }, { "name": "library-nonet", "targetType": "library", "dependencies": { "vibe-d": {"version": "~>0.7.19-rc.4", "optional": true} }, "excludedSourceFiles": ["source/app.d"] } ] } dub-0.9.24/dub.selections.json000066400000000000000000000003001267257315000161750ustar00rootroot00000000000000{ "fileVersion": 1, "versions": { "memutils": "0.3.2", "libevent": "2.0.1+2.0.16", "vibe-d": "0.7.23", "openssl": "1.1.4+1.0.1g", "libev": "5.0.0+4.04", "libasync": "0.7.1" } } dub-0.9.24/examples/000077500000000000000000000000001267257315000142065ustar00rootroot00000000000000dub-0.9.24/examples/app-sdl/000077500000000000000000000000001267257315000155465ustar00rootroot00000000000000dub-0.9.24/examples/app-sdl/dub.sdl000066400000000000000000000000721267257315000170230ustar00rootroot00000000000000name "app-example"; description "A simple D application"; dub-0.9.24/examples/app-sdl/source/000077500000000000000000000000001267257315000170465ustar00rootroot00000000000000dub-0.9.24/examples/app-sdl/source/app.d000066400000000000000000000000761267257315000177760ustar00rootroot00000000000000import std.stdio; void main() { writeln("Hello, World."); } dub-0.9.24/examples/app/000077500000000000000000000000001267257315000147665ustar00rootroot00000000000000dub-0.9.24/examples/app/dub.json000066400000000000000000000001051267257315000164270ustar00rootroot00000000000000{ "name": "app-example", "description": "A simple D application" } dub-0.9.24/examples/app/source/000077500000000000000000000000001267257315000162665ustar00rootroot00000000000000dub-0.9.24/examples/app/source/app.d000066400000000000000000000000761267257315000172160ustar00rootroot00000000000000import std.stdio; void main() { writeln("Hello, World."); } dub-0.9.24/examples/generated-sources/000077500000000000000000000000001267257315000176255ustar00rootroot00000000000000dub-0.9.24/examples/generated-sources/dub.json000066400000000000000000000003041267257315000212670ustar00rootroot00000000000000{ "name": "generated-sources", "description": "Example of using pre generate commands to generate source code.", "preGenerateCommands": [ "echo int fun() { return 42; } > source/test.d" ] } dub-0.9.24/examples/generated-sources/source/000077500000000000000000000000001267257315000211255ustar00rootroot00000000000000dub-0.9.24/examples/generated-sources/source/app.d000066400000000000000000000001201267257315000220430ustar00rootroot00000000000000import std.stdio; import test; void main() { writefln("Result: %s", fun()); } dub-0.9.24/examples/header-lib/000077500000000000000000000000001267257315000162025ustar00rootroot00000000000000dub-0.9.24/examples/header-lib/dub.json000066400000000000000000000002361267257315000176500ustar00rootroot00000000000000{ "name": "header-lib-example", "description": "A simple D header library (C binding to libmylib.so)", "targetType": "sourceLibrary", "libs": ["mylib"] } dub-0.9.24/examples/header-lib/import/000077500000000000000000000000001267257315000175145ustar00rootroot00000000000000dub-0.9.24/examples/header-lib/import/mylib.d000066400000000000000000000000461267257315000207750ustar00rootroot00000000000000module mylib; extern(C) void test(); dub-0.9.24/examples/lib-user/000077500000000000000000000000001267257315000157305ustar00rootroot00000000000000dub-0.9.24/examples/lib-user/dub.json000066400000000000000000000002641267257315000173770ustar00rootroot00000000000000{ "name": "lib-user-example", "description": "An application using a local library dependency", "dependencies": { "lib-example": {"version": "~master", "path": "../lib"} } } dub-0.9.24/examples/lib-user/source/000077500000000000000000000000001267257315000172305ustar00rootroot00000000000000dub-0.9.24/examples/lib-user/source/app.d000066400000000000000000000000461267257315000201550ustar00rootroot00000000000000import lib; void main() { test(); } dub-0.9.24/examples/lib/000077500000000000000000000000001267257315000147545ustar00rootroot00000000000000dub-0.9.24/examples/lib/dub.json000066400000000000000000000001331267257315000164160ustar00rootroot00000000000000{ "name": "lib-example", "description": "A simple D library", "targetType": "library" } dub-0.9.24/examples/lib/source/000077500000000000000000000000001267257315000162545ustar00rootroot00000000000000dub-0.9.24/examples/lib/source/lib.d000066400000000000000000000001131267257315000171620ustar00rootroot00000000000000module lib; import std.stdio; void test() { writeln("Hello, World."); } dub-0.9.24/examples/mixed/000077500000000000000000000000001267257315000153145ustar00rootroot00000000000000dub-0.9.24/examples/mixed/dub.json000066400000000000000000000001471267257315000167630ustar00rootroot00000000000000{ "name": "mixed-example", "description": "A package usable as both, an application and a library" } dub-0.9.24/examples/mixed/source/000077500000000000000000000000001267257315000166145ustar00rootroot00000000000000dub-0.9.24/examples/mixed/source/app.d000066400000000000000000000000631267257315000175400ustar00rootroot00000000000000module app; import lib; void main() { test(); } dub-0.9.24/examples/mixed/source/lib.d000066400000000000000000000001131267257315000175220ustar00rootroot00000000000000module lib; import std.stdio; void test() { writeln("Hello, World!"); } dub-0.9.24/examples/vibed-main/000077500000000000000000000000001267257315000162215ustar00rootroot00000000000000dub-0.9.24/examples/vibed-main/dub.json000066400000000000000000000002671267257315000176730ustar00rootroot00000000000000{ "name": "vibed-main-example", "description": "A project using vibe.d and a custom main() function", "dependencies": { "vibe-d": "~master" }, "versions": ["VibeCustomMain"] } dub-0.9.24/examples/vibed-main/source/000077500000000000000000000000001267257315000175215ustar00rootroot00000000000000dub-0.9.24/examples/vibed-main/source/app.d000066400000000000000000000003451267257315000204500ustar00rootroot00000000000000import vibe.vibe; void main() { listenHTTP(new HTTPServerSettings, &handleRequest); lowerPrivileges(); runEventLoop(); } void handleRequest(HTTPServerRequest req, HTTPServerResponse res) { res.writeBody("Hello, World!"); } dub-0.9.24/examples/vibed/000077500000000000000000000000001267257315000152775ustar00rootroot00000000000000dub-0.9.24/examples/vibed/dub.json000066400000000000000000000001641267257315000167450ustar00rootroot00000000000000{ "name": "vibed-example", "description": "A project using vibe.d", "dependencies": { "vibe-d": "~master" } } dub-0.9.24/examples/vibed/source/000077500000000000000000000000001267257315000165775ustar00rootroot00000000000000dub-0.9.24/examples/vibed/source/app.d000066400000000000000000000003061267257315000175230ustar00rootroot00000000000000import vibe.d; shared static this() { listenHTTP(new HTTPServerSettings, &handleRequest); } void handleRequest(HTTPServerRequest req, HTTPServerResponse res) { res.writeBody("Hello, World!"); } dub-0.9.24/scripts/000077500000000000000000000000001267257315000140575ustar00rootroot00000000000000dub-0.9.24/scripts/bash-completion/000077500000000000000000000000001267257315000171435ustar00rootroot00000000000000dub-0.9.24/scripts/bash-completion/dub.bash000066400000000000000000000036661267257315000205670ustar00rootroot00000000000000# 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-0.9.24/scripts/fish-completion/000077500000000000000000000000001267257315000171575ustar00rootroot00000000000000dub-0.9.24/scripts/fish-completion/dub.fish000066400000000000000000000162271267257315000206140ustar00rootroot00000000000000# # 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-nobounds unittest profile docs ddox cov unittest-cov" 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-0.9.24/scripts/rpm-package/000077500000000000000000000000001267257315000162465ustar00rootroot00000000000000dub-0.9.24/scripts/rpm-package/dub.spec000066400000000000000000000017611267257315000177010ustar00rootroot00000000000000## 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-0.9.24/scripts/rpm-package/make_installer.sh000066400000000000000000000010571267257315000215770ustar00rootroot00000000000000#!/bin/sh 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 installer/rpm/ 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-0.9.24/scripts/win-installer/000077500000000000000000000000001267257315000166475ustar00rootroot00000000000000dub-0.9.24/scripts/win-installer/EnvVarUpdate.nsh000066400000000000000000000251571267257315000217370ustar00rootroot00000000000000/** * 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 then 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-0.9.24/scripts/win-installer/banner.bmp000066400000000000000000004556561267257315000206410ustar00rootroot00000000000000BM[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-0.9.24/scripts/win-installer/header.bmp000066400000000000000000000623321267257315000206050ustar00rootroot00000000000000BMd6(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-0.9.24/scripts/win-installer/installer.nsi000066400000000000000000000111771267257315000213660ustar00rootroot00000000000000SetCompressor /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-0.9.24/scripts/win-installer/make_installer.cmd000066400000000000000000000002311267257315000223220ustar00rootroot00000000000000set GITVER=unknown for /f %%i in ('git describe --tags') do set GITVER=%%i "%ProgramFiles(x86)%\NSIS\makensis.exe" "/DVersion=%GITVER:~1%" installer.nsi dub-0.9.24/source/000077500000000000000000000000001267257315000136705ustar00rootroot00000000000000dub-0.9.24/source/app.d000066400000000000000000000005131267257315000146140ustar00rootroot00000000000000/** Application entry point. Copyright: © 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 app; import dub.commandline; int main(string[] args) { version (unittest) return 0; else return runDubCommandLine(args); } dub-0.9.24/source/dub/000077500000000000000000000000001267257315000144425ustar00rootroot00000000000000dub-0.9.24/source/dub/commandline.d000066400000000000000000001561761267257315000171150ustar00rootroot00000000000000/** Defines the behavior of the DUB command line client. Copyright: © 2012-2013 Matthias Dondorff, Copyright © 2012-2014 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.packagesupplier; import dub.platform : determineCompiler; import dub.project; import dub.internal.utils : getDUBVersion, getClosestMatch; 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; CommandGroup[] getCommands() { return [ CommandGroup("Package creation", new InitCommand ), CommandGroup("Build, test and run", new RunCommand, new BuildCommand, new TestCommand, new GenerateCommand, new DescribeCommand, new CleanCommand, new DustmiteCommand ), CommandGroup("Package management", new FetchCommand, new InstallCommand, new RemoveCommand, new UninstallCommand, new UpgradeCommand, new AddPathCommand, new RemovePathCommand, new AddLocalCommand, new RemoveLocalCommand, new ListCommand, new ListInstalledCommand, new AddOverrideCommand, new RemoveOverrideCommand, new ListOverridesCommand, new CleanCachesCommand, ) ]; } 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("/", "\\"); } // 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; options.root_path = getcwd(); 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; 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; } // create the list of all supported commands CommandGroup[] commands = getCommands(); // 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(Path(getcwd())); } else { // initialize DUB auto package_suppliers = options.registry_urls.map!(url => cast(PackageSupplier)new RegistryPackageSupplier(URL(url))).array; dub = new Dub(package_suppliers, options.root_path, options.skipRegistry); dub.dryRun = options.annotate; // make the CWD package available so that for example sub packages can reference their // parent package. try dub.packageManager.getOrLoadPackage(Path(options.root_path)); catch (Exception e) { logDiagnostic("No package found in current working directory."); } } } // execute the command int rc; try { rc = 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; } if (!cmd.skipDubInitialization) dub.shutdown(); return rc; } struct CommonOptions { bool verbose, vverbose, quiet, vquiet; bool help, annotate, bare; string[] registry_urls; string root_path; SkipRegistry skipRegistry = SkipRegistry.none; 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 DUB registry URL first when resolving dependencies. Can be specified multiple times."]); args.getopt("skip-registry", &skipRegistry, [ "Skips searching certain package registries for dependencies:", " none: Search all configured registries (default)", " standard: Don't search on "~defaultRegistryURL, " all: Search none of the configured registries", ]); 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("vquiet", &vquiet, ["Print no messages"]); args.getopt("cache", &defaultPlacementLocation, ["Puts any fetched packages in the specified location [local|system|user]."]); } } class CommandArgs { struct Arg { Variant defaultValue; Variant value; string names; string[] helpText; } private { string[] m_args; Arg[] m_recognizedArgs; } this(string[] args) { m_args = "dummy" ~ args; } @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; } void dropAllArgs() { m_args = null; } string[] extractRemainingArgs() { auto ret = m_args[1 .. $]; m_args = null; return ret; } } class Command { string name; string argumentsPattern; string description; string[] helpText; bool acceptsAppArgs; bool hidden = false; // used for deprecated commands bool skipDubInitialization = false; abstract void prepare(scope CommandArgs args); abstract int execute(Dub dub, string[] free_args, string[] app_args); } struct CommandGroup { string caption; Command[] commands; this(string caption, Command[] commands...) { this.caption = caption; this.commands = commands.dup; } } /******************************************************************************/ /* INIT */ /******************************************************************************/ class InitCommand : Command { private{ string m_buildType = "minimal"; PackageFormat m_format = PackageFormat.sdl; } 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 dirctory is used." ]; } override void prepare(scope CommandArgs args) { args.getopt("t|type", &m_buildType, [ "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", ]); args.getopt("f|format", &m_format, [ "Sets the format to use for the package description file. Possible values:", " sdl, json" ]); } override int execute(Dub dub, string[] free_args, string[] app_args) { string dir; enforceUsage(app_args.empty, "Unexpected application arguments."); if (free_args.length) { dir = free_args[0]; free_args = free_args[1 .. $]; } //TODO: Remove this block in next version // Checks if argument uses current method of specifying project type. if (free_args.length) { if (["vibe.d", "deimos", "minimal"].canFind(free_args[0])) { m_buildType = free_args[0]; free_args = free_args[1 .. $]; logInfo("Deprecated use of init type. Use --type=[vibe.d | deimos | minimal] in future."); } } dub.createEmptyPackage(Path(dir), free_args, m_buildType, m_format); 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; Compiler m_compiler; BuildPlatform m_buildPlatform; BuildSettings m_buildSettings; string m_defaultConfig; bool m_nodeps; bool m_forceRemove = 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-nobounds, unittest, profile, docs, ddox, cov, unittest-cov and custom types" ]); args.getopt("c|config", &m_buildConfig, [ "Builds the specified configuration. Configurations can be defined in dub.json" ]); 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 check/update dependencies before building" ]); args.getopt("force-remove", &m_forceRemove, [ "Force deletion of fetched packages with untracked files when upgrading" ]); args.getopt("build-mode", &m_buildMode, [ "Specifies the way the compiler and linker are invoked. Valid values:", " separate (default), allAtOnce, singleFile" ]); } protected void setupPackage(Dub dub, string package_name) { if (!m_compilerName.length) m_compilerName = dub.defaultCompiler; 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 = "debug"; } if (!m_nodeps) { // TODO: only upgrade(select) if necessary, only upgrade(upgrade) every now and then // retrieve missing packages logDiagnostic("Checking for missing dependencies."); dub.upgrade(UpgradeOptions.select); // check for updates logDiagnostic("Checking for upgrades."); dub.upgrade(UpgradeOptions.upgrade|UpgradeOptions.printUpgradesOnly|UpgradeOptions.useCachedResult); } dub.project.validate(); } private bool loadSpecificPackage(Dub dub, string package_name) { // load package in root_path to enable searching for sub packages if (loadCwdPackage(dub, package_name.length == 0)) { if (package_name.startsWith(":")) package_name = dub.projectName ~ package_name; if (!package_name.length) return true; } auto pack = dub.packageManager.getFirstPackage(package_name); enforce(pack, "Failed to find a package named '"~package_name~"'."); logInfo("Building package %s in %s", pack.name, pack.path.toNativeString()); dub.rootPath = pack.path; dub.loadPackage(pack); return true; } 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.loadPackageFromCwd(); 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.run = m_run; gensettings.runArgs = app_args; gensettings.force = m_force; gensettings.rdmd = m_rdmd; gensettings.tempBuild = m_tempBuild; gensettings.parallelBuild = m_parallel; logDiagnostic("Generating using %s", m_generator); dub.generateProject(m_generator, gensettings); if (m_buildType == "ddox") dub.runDdox(gensettings.run); return 0; } } class BuildCommand : GenerateCommand { 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" ]); super.prepare(args); m_generator = "build"; } override int execute(Dub dub, string[] free_args, string[] app_args) { return super.execute(dub, free_args, app_args); } } 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_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; m_buildType = "unittest"; } 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("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); 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.force = m_force; settings.run = true; settings.runArgs = app_args; dub.testProject(settings, m_buildConfig, Path(m_mainFile)); 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(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; if (m_importPaths) { dub.listImportPaths(m_buildPlatform, config, m_buildType, m_dataNullDelim); } else if (m_stringImportPaths) { dub.listStringImportPaths(m_buildPlatform, config, m_buildType, m_dataNullDelim); } else if (m_data) { dub.listProjectData(m_buildPlatform, config, m_buildType, m_data, m_dataList? null : m_compiler, m_dataNullDelim); } else { auto desc = dub.project.describe(m_buildPlatform, config, m_buildType); 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) { foreach (p; dub.packageManager.getPackageIterator()) dub.cleanPackage(p.path); } else { dub.cleanPackage(dub.rootPath); } return 0; } } /******************************************************************************/ /* FETCH / REMOVE / UPGRADE */ /******************************************************************************/ class UpgradeCommand : Command { private { bool m_prerelease = false; bool m_forceRemove = false; bool m_missingOnly = false; bool m_verify = false; } this() { this.name = "upgrade"; this.argumentsPattern = "[]"; this.description = "Forces an upgrade of all dependencies"; this.helpText = [ "Upgrades all dependencies of the package by querying the package registry(ies) for new versions.", "", "This will also update the versions stored in the selections file ("~SelectedVersions.defaultFile~") accordingly.", "", "If a package specified, (only) that package will be upgraded. Otherwise all direct and indirect dependencies of the current 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("force-remove", &m_forceRemove, [ "Force deletion of fetched packages with untracked files" ]); args.getopt("verify", &m_verify, [ "Updates the project and performs a build. If successfull, rewrites the selected versions file ." ]); 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." ]); } 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.loadPackageFromCwd(); 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_forceRemove) options |= UpgradeOptions.forceRemove; enforceUsage(app_args.length == 0, "Upgrading a specific package is not yet implemented."); dub.upgrade(options); return 0; } } class FetchRemoveCommand : Command { protected { string m_version; bool m_forceRemove = false; bool m_system = false; bool m_local = 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("system", &m_system, ["Deprecated: Puts the package into the system wide package cache instead of the user local one."]); args.getopt("local", &m_local, ["Deprecated: Puts the package into a sub folder of the current working directory. Cannot be mixed with --system."]); args.getopt("force-remove", &m_forceRemove, [ "Force deletion of fetched packages with untracked files" ]); } 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 the \"dependencies\" field in the package description file (e.g. dub.json) 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 to a place where several applications can share these. If you just have an dependency to a package, just add it to your dub.json, 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 --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(!m_local || !m_system, "--local and --system are exclusive to each other."); enforceUsage(free_args.length == 1, "Expecting exactly one argument."); enforceUsage(app_args.length == 0, "Unexpected application arguments."); auto location = defaultPlacementLocation; if (m_local) { logWarn("--local is deprecated. Use --cache=local instead."); location = PlacementLocation.local; } else if (m_system) { logWarn("--system is deprecated. Use --cache=system instead."); location = PlacementLocation.system; } auto name = free_args[0]; FetchOptions fetchOpts; fetchOpts |= FetchOptions.forceBranchUpgrade; fetchOpts |= m_forceRemove ? FetchOptions.forceRemove : FetchOptions.none; if (m_version.length) dub.fetch(name, Dependency(m_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 { 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); } 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 = defaultPlacementLocation; if (m_local) { logWarn("--local is deprecated. Use --cache=local instead."); location = PlacementLocation.local; } else if (m_system) { logWarn("--system is deprecated. Use --cache=system instead."); location = PlacementLocation.system; } dub.remove(package_id, m_version, location, m_forceRemove); 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 path to package."); 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) { logInfo("Packages present in the system and known to dub:"); foreach (p; dub.packageManager.getPackageIterator()) logInfo(" %s %s: %s", p.name, p.ver, p.path.toNativeString()); logInfo(""); return 0; } } class ListInstalledCommand : ListCommand { this() { this.name = "list-installed"; hidden = true; } override void prepare(scope CommandArgs args) { super.prepare(args); } override int execute(Dub dub, string[] free_args, string[] app_args) { warnRenamed("list-installed", "list"); return super.execute(dub, free_args, app_args); } } /******************************************************************************/ /* 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(Path(free_args[2]))) { auto target = Path(free_args[2]); 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 overriden 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) { dub.cleanCaches(); 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 liner 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) { if (m_testPackage.length) { dub = new Dub(Path(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.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 = Path(free_args[0]); path.normalize(); enforceUsage(path.length > 0, "Destination path must not be empty."); if (!path.absolute) path = Path(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(Path folder, Path 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); } } } } 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); // overwrite package description file with additional version information pack_.storeInfo(dst_path); } logInfo("Executing dustmite..."); auto testcmd = format("%s dustmite --vquiet --test-package=%s -b %s -c %s --compiler %s -a %s", thisExePath, prj.name, m_buildType, m_buildConfig, m_compilerName, m_arch); if (m_compilerStatusCode != int.min) testcmd ~= format(" --compiler-status=%s", m_compilerStatusCode); if (m_compilerRegex.length) testcmd ~= format(" \"--compiler-regex=%s\"", m_compilerRegex); if (m_linkerStatusCode != int.min) testcmd ~= format(" --linker-status=%s", m_linkerStatusCode); if (m_linkerRegex.length) testcmd ~= format(" \"--linker-regex=%s\"", m_linkerRegex); if (m_programStatusCode != int.min) testcmd ~= format(" --program-status=%s", m_programStatusCode); if (m_programRegex.length) testcmd ~= format(" \"--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]); 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); } } } /******************************************************************************/ /* 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); } dub-0.9.24/source/dub/compilers/000077500000000000000000000000001267257315000164375ustar00rootroot00000000000000dub-0.9.24/source/dub/compilers/buildsettings.d000066400000000000000000000302611267257315000214660ustar00rootroot00000000000000/** 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; import std.path : globMatch; static if (__VERSION__ >= 2067) import std.typecons : BitFlags; /// BuildPlatform specific settings, like needed libraries or additional /// include paths. struct BuildSettings { import dub.internal.vibecompat.data.serialization; TargetType targetType; string targetPath; string targetName; string workingDirectory; string mainSourceFile; string[] dflags; string[] lflags; string[] libs; string[] linkerFiles; string[] sourceFiles; string[] copyFiles; string[] versions; string[] debugVersions; string[] importPaths; string[] stringImportPaths; string[] importFiles; string[] stringImportFiles; string[] preGenerateCommands; string[] postGenerateCommands; string[] preBuildCommands; string[] postBuildCommands; @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); addVersions(bs.versions); addDebugVersions(bs.debugVersions); addImportPaths(bs.importPaths); addStringImportPaths(bs.stringImportPaths); addImportFiles(bs.importFiles); addStringImportFiles(bs.stringImportFiles); addPreGenerateCommands(bs.preGenerateCommands); addPostGenerateCommands(bs.postGenerateCommands); addPreBuildCommands(bs.preBuildCommands); addPostBuildCommands(bs.postBuildCommands); } void addDFlags(in string[] value...) { 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 addVersions(in string[] value...) { add(versions, value); } void addDebugVersions(in string[] value...) { add(debugVersions, 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 removeImportFiles(in string[] value...) { removePaths(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 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; } // Adds vals to arr without adding duplicates. private void add(ref string[] arr, in string[] vals, bool no_duplicates = true) { if (!no_duplicates) { arr ~= vals; return; } foreach (v; vals) { bool found = false; foreach (i; 0 .. arr.length) if (arr[i] == v) { found = true; break; } if (!found) arr ~= v; } } private void prepend(ref string[] arr, in string[] vals, bool no_duplicates = true) { if (!no_duplicates) { arr = vals ~ arr; return; } foreach_reverse (v; vals) { bool found = false; foreach (i; 0 .. arr.length) if (arr[i] == v) { found = true; break; } if (!found) arr = v ~ arr; } } // add string import files (avoids file name duplicates in addition to path duplicates) private void addSI(ref string[] arr, in string[] vals) { outer: foreach (v; vals) { auto vh = Path(v).head; foreach (ve; arr) { if (Path(ve).head == vh) continue outer; } arr ~= v; } } private void removePaths(ref string[] arr, in string[] vals) { bool matches(string s) { foreach (p; vals) if (Path(s) == Path(p) || globMatch(s, p)) return true; return false; } arr = arr.filter!(s => !matches(s))().array(); } private void remove(ref string[] arr, in string[] vals) { bool matches(string s) { foreach (p; vals) if (s == p) return true; return false; } arr = arr.filter!(s => !matches(s))().array(); } } 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; static if (__VERSION__ >= 2067) { @ignore BitFlags!BuildRequirement values; this(BuildRequirement req) { values = req; } deprecated("Use BuildRequirement.* instead.") { enum none = BuildRequirement.none; enum allowWarnings = BuildRequirement.allowWarnings; enum silenceWarnings = BuildRequirement.silenceWarnings; enum disallowDeprecations = BuildRequirement.disallowDeprecations; enum silenceDeprecations = BuildRequirement.silenceDeprecations; enum disallowInlining = BuildRequirement.disallowInlining; enum disallowOptimization = BuildRequirement.disallowOptimization; enum requireBoundsCheck = BuildRequirement.requireBoundsCheck; enum requireContracts = BuildRequirement.requireContracts; enum relaxProperties = BuildRequirement.relaxProperties; enum noDefaultFlags = BuildRequirement.noDefaultFlags; } } else { @ignore BuildRequirement values; this(BuildRequirement req) { values = req; } BuildRequirement[] toRepresentation() const { BuildRequirement[] ret; for (int f = 1; f <= BuildRequirement.max; f *= 2) if (values & f) ret ~= cast(BuildRequirement)f; return ret; } static BuildRequirements fromRepresentation(BuildRequirement[] v) { BuildRequirements ret; foreach (f; v) ret.values |= f; return ret; } } 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 } struct BuildOptions { import dub.internal.vibecompat.data.serialization : ignore; static if (__VERSION__ >= 2067) { @ignore BitFlags!BuildOption values; this(BuildOption opt) { values = opt; } deprecated("Use BuildOption.* instead.") { enum none = BuildOption.none; enum debugMode = BuildOption.debugMode; enum releaseMode = BuildOption.releaseMode; enum coverage = BuildOption.coverage; enum debugInfo = BuildOption.debugInfo; enum debugInfoC = BuildOption.debugInfoC; enum alwaysStackFrame = BuildOption.alwaysStackFrame; enum stackStomping = BuildOption.stackStomping; enum inline = BuildOption.inline; enum noBoundsCheck = BuildOption.noBoundsCheck; enum optimize = BuildOption.optimize; enum profile = BuildOption.profile; enum unittests = BuildOption.unittests; enum verbose = BuildOption.verbose; enum ignoreUnknownPragmas = BuildOption.ignoreUnknownPragmas; enum syntaxOnly = BuildOption.syntaxOnly; enum warnings = BuildOption.warnings; enum warningsAsErrors = BuildOption.warningsAsErrors; enum ignoreDeprecations = BuildOption.ignoreDeprecations; enum deprecationWarnings = BuildOption.deprecationWarnings; enum deprecationErrors = BuildOption.deprecationErrors; enum property = BuildOption.property; } } else { @ignore BuildOption values; this(BuildOption opt) { values = opt; } BuildOption[] toRepresentation() const { BuildOption[] ret; for (int f = 1; f <= BuildOption.max; f *= 2) if (values & f) ret ~= cast(BuildOption)f; return ret; } static BuildOptions fromRepresentation(BuildOption[] v) { BuildOptions ret; foreach (f; v) ret.values |= f; return ret; } } alias values this; } dub-0.9.24/source/dub/compilers/compiler.d000066400000000000000000000452361267257315000204300ustar00rootroot00000000000000/** Compiler settings and abstraction. 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.compiler; public import dub.compilers.buildsettings; import dub.compilers.dmd; import dub.compilers.gdc; import dub.compilers.ldc; 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 std.algorithm; import std.array; import std.conv; import std.exception; import std.process; static this() { registerCompiler(new DmdCompiler); registerCompiler(new GdcCompiler); registerCompiler(new LdcCompiler); } 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); } string defaultCompiler() { static string name; if (!name.length) name = findCompiler(); return name; } private string findCompiler() { import std.process : env=environment; version (Windows) enum sep = ";", exe = ".exe"; version (Posix) enum sep = ":", exe = ""; auto compilers = ["dmd", "gdc", "gdmd", "ldc2", "ldmd2"]; auto paths = env.get("PATH", "").splitter(sep).map!Path; auto res = compilers.find!(bin => paths.canFind!(p => existsFile(p ~ (bin~exe)))); return res.empty ? compilers[0] : res.front; } void registerCompiler(Compiler c) { s_compilers ~= c; } void warnOnSpecialCompilerFlags(string[] compiler_flags, BuildOptions options, string package_name, string config_name) { 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"], `Use --arch=x86/--arch=x86_64 to specify the target architecture`} ]; 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.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(""); } /** Alters the build options to comply with the specified build requirements. */ 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; } /** 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) { import std.string : format; 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; version(Windows) settings.sourceFiles = settings.sourceFiles.filter!(f => !f.endsWith(".lib")).array; } version (Posix) { 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("-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."); } } } interface Compiler { @property string name() const; 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, 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; /// 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; 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)); } } /// Represents a platform a package can be build upon. struct BuildPlatform { /// e.g. ["posix", "windows"] string[] platform; /// 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. 2065) int frontendVersion; enum any = BuildPlatform(null, null, null, null, -1); /// Build platforms can be specified via a string specification. /// /// 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: /// specification = The specification being matched. It must be the empty string or start with a dash. /// /// Returns: /// true if the given specification matches this BuildPlatform, false otherwise. (The empty string matches) /// bool matchesSpecification(const(char)[] specification) const { import std.string : format; if (specification.empty) return true; if (this == 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.canFind(splitted.front)) { splitted.popFront(); if(splitted.empty) return true; } if (architecture.canFind(splitted.front)) { splitted.popFront(); if(splitted.empty) return true; } if (compiler == splitted.front) { splitted.popFront(); enforce(splitted.empty, "No valid specification! The compiler has to be the last element!"); return true; } return false; } unittest { auto platform=BuildPlatform(["posix", "linux"], ["x86_64"], "dmd"); 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")); } } string getTargetFileName(in BuildSettings settings, in BuildPlatform platform) { 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; case TargetType.library: case TargetType.staticLibrary: if (platform.platform.canFind("windows") && platform.compiler == "dmd") return settings.targetName ~ ".lib"; else return "lib" ~ settings.targetName ~ ".a"; case TargetType.dynamicLibrary: if( platform.platform.canFind("windows") ) return settings.targetName ~ ".dll"; else return "lib" ~ settings.targetName ~ ".so"; case TargetType.object: if (platform.platform.canFind("windows")) return settings.targetName ~ ".obj"; else return settings.targetName ~ ".o"; } } bool isLinkerFile(string f) { import std.path; switch (extension(f)) { default: return false; version (Windows) { case ".lib", ".obj", ".res", ".def": return true; } else { case ".a", ".o", ".so", ".dylib": return true; } } } /// Generate a file that will give, at compile time, informations about the compiler (architecture, frontend version...) Path generatePlatformProbeFile() { import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; import dub.internal.utils; auto path = getTempFile("dub_platform_probe", ".d"); auto fil = openFile(path, FileMode.createTrunc); scope (failure) { fil.close(); } fil.write(q{ module dub_platform_probe; template toString(int v) { enum toString = v.stringof; } pragma(msg, `{`); pragma(msg,` "compiler": "`~ determineCompiler() ~ `",`); pragma(msg, ` "frontendVersion": ` ~ toString!__VERSION__ ~ `,`); pragma(msg, ` "compilerVendor": "` ~ __VENDOR__ ~ `",`); pragma(msg, ` "platform": [`); pragma(msg, ` ` ~ determinePlatform()); pragma(msg, ` ],`); pragma(msg, ` "architecture": [`); pragma(msg, ` ` ~ determineArchitecture()); pragma(msg, ` ],`); pragma(msg, `}`); string determinePlatform() { 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", `; return ret; } string determineArchitecture() { string ret; version(X86) ret ~= `"x86", `; version(X86_64) ret ~= `"x86_64", `; version(ARM) ret ~= `"arm", `; version(ARM_Thumb) ret ~= `"arm_thumb", `; version(ARM_SoftFloat) ret ~= `"arm_softfloat", `; version(ARM_HardFloat) ret ~= `"arm_hardfloat", `; version(ARM64) ret ~= `"arm64", `; 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; } string determineCompiler() { version(DigitalMars) return "dmd"; else version(GNU) return "gdc"; else version(LDC) return "ldc"; else version(SDC) return "sdc"; else return null; } }); fil.close(); return path; } BuildPlatform readPlatformProbe(string output) { import std.string; // work around possible additional output of the compiler auto idx1 = output.indexOf("{"); auto idx2 = output.lastIndexOf("}"); enforce(idx1 >= 0 && idx1 < idx2, "Unexpected platform information output - does not contain a JSON object."); output = output[idx1 .. idx2+1]; 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; } private { Compiler[] s_compilers; } dub-0.9.24/source/dub/compilers/dmd.d000066400000000000000000000172461267257315000173620ustar00rootroot00000000000000/** 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.internal.utils; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import dub.platform; import std.algorithm; import std.array; import std.conv; import std.exception; import std.file; import std.process; import std.random; import std.typecons; 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, ["-gc"]), 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"]), ]; @property string name() const { return "dmd"; } BuildPlatform determinePlatform(ref BuildSettings settings, string compiler_binary, string arch_override) { import std.process; import std.string; auto fil = generatePlatformProbeFile(); string[] arch_flags; switch (arch_override) { default: throw new Exception("Unsupported architecture: "~arch_override); case "": break; case "x86": arch_flags = ["-m32"]; break; case "x86_64": arch_flags = ["-m64"]; break; } settings.addDFlags(arch_flags); auto result = executeShell(escapeShellCommand(compiler_binary ~ arch_flags ~ ["-quiet", "-c", "-o-", 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 = readPlatformProbe(result.output); build_platform.compilerBinary = compiler_binary; if (build_platform.compiler != this.name) { logWarn(`The determined compiler type "%s" doesn't match the expected type "%s". This will probably result in build errors.`, build_platform.compiler, this.name); } 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; } void prepareBuildSettings(ref BuildSettings settings, 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.sourceFiles)) { settings.addDFlags(settings.sourceFiles); settings.sourceFiles = null; } if (!(fields & BuildSetting.libs)) { resolveLibs(settings); version(Windows) settings.addSourceFiles(settings.libs.map!(l => l~".lib")().array()); else settings.addLFlags(settings.libs.map!(l => "-l"~l)().array()); } if (!(fields & BuildSetting.lflags)) { settings.addDFlags(lflagsToDFlags(settings.lflags)); settings.lflags = null; } version (Posix) { if (settings.targetType == TargetType.dynamicLibrary) 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; } 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: version (Windows) settings.addDFlags("-shared"); else settings.addDFlags("-shared", "-defaultlib=libphobos2.so"); break; case TargetType.object: settings.addDFlags("-c"); break; } if (tpath is null) tpath = (Path(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 = Path(settings.targetPath) ~ getTargetFileName(settings, platform); auto args = ["-of"~tpath.toNativeString()]; args ~= objects; args ~= settings.sourceFiles; version(linux) args ~= "-L--no-as-needed"; // avoids linker errors due to libraries being speficied 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 lflags.map!(f => "-L"~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-0.9.24/source/dub/compilers/gdc.d000066400000000000000000000176331267257315000173530ustar00rootroot00000000000000/** 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.internal.utils; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import dub.platform; import std.algorithm; import std.array; import std.conv; import std.exception; import std.file; import std.process; import std.random; 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, ["-?"]), ]; @property string name() const { return "gdc"; } BuildPlatform determinePlatform(ref BuildSettings settings, string compiler_binary, string arch_override) { import std.process; import std.string; auto fil = generatePlatformProbeFile(); 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); auto binary_file = getTempFile("dub_platform_probe"); auto result = executeShell(escapeShellCommand( compiler_binary ~ arch_flags ~ ["-c", "-o", binary_file.toNativeString(), 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 = readPlatformProbe(result.output); build_platform.compilerBinary = compiler_binary; if (build_platform.compiler != this.name) { logWarn(`The determined compiler type "%s" doesn't match the expected type "%s". This will probably result in build errors.`, build_platform.compiler, this.name); } 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; } void prepareBuildSettings(ref BuildSettings settings, 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); settings.addDFlags(settings.libs.map!(l => "-l"~l)().array()); } if (!(fields & BuildSetting.lflags)) { settings.addDFlags(lflagsToDFlags(settings.lflags)); settings.lflags = null; } if (settings.targetType == TargetType.dynamicLibrary) 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; } 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 = (Path(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; version(linux) args ~= "-L--no-as-needed"; // avoids linker errors due to libraries being speficied in the wrong order by DMD } logDiagnostic("%s", args.join(" ")); invokeTool(args, output_callback); } string[] lflagsToDFlags(in string[] lflags) const { string[] dflags; foreach( f; lflags ) { 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-0.9.24/source/dub/compilers/ldc.d000066400000000000000000000140501267257315000173460ustar00rootroot00000000000000/** 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.internal.utils; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import dub.platform; import std.algorithm; import std.array; import std.conv; import std.exception; import std.file; import std.process; import std.random; import std.typecons; class LdcCompiler : Compiler { private static immutable s_options = [ tuple(BuildOption.debugMode, ["-d-debug"]), tuple(BuildOption.releaseMode, ["-release"]), //tuple(BuildOption.coverage, ["-?"]), tuple(BuildOption.debugInfo, ["-g"]), tuple(BuildOption.debugInfoC, ["-gc"]), //tuple(BuildOption.alwaysStackFrame, ["-?"]), //tuple(BuildOption.stackStomping, ["-?"]), tuple(BuildOption.inline, ["-enable-inlining"]), tuple(BuildOption.noBoundsCheck, ["-disable-boundscheck"]), tuple(BuildOption.optimize, ["-O"]), //tuple(BuildOption.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, ["-?"]), ]; @property string name() const { return "ldc"; } BuildPlatform determinePlatform(ref BuildSettings settings, string compiler_binary, string arch_override) { // TODO: determine platform by invoking the compiler instead BuildPlatform build_platform; build_platform.platform = .determinePlatform(); build_platform.architecture = .determineArchitecture(); build_platform.compiler = this.name; build_platform.compilerBinary = compiler_binary; switch (arch_override) { default: throw new Exception("Unsupported architecture: "~arch_override); case "": break; case "x86": build_platform.architecture = ["x86"]; settings.addDFlags("-march=x86"); break; case "x86_64": build_platform.architecture = ["x86_64"]; settings.addDFlags("-march=x86-64"); break; } return build_platform; } void prepareBuildSettings(ref BuildSettings settings, 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); settings.addLFlags(settings.libs.map!(l => "-l"~l)().array()); } if (!(fields & BuildSetting.lflags)) { settings.addDFlags(lflagsToDFlags(settings.lflags)); settings.lflags = null; } if (settings.targetType == TargetType.dynamicLibrary) 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; } 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", "-defaultlib=phobos2"); break; case TargetType.object: settings.addDFlags("-c"); break; } if (tpath is null) tpath = (Path(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"); std.file.write(res_file.toNativeString(), join(cast(string[])settings.dflags, "\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) { assert(false, "Separate linking not implemented for LDC"); } string[] lflagsToDFlags(in string[] lflags) const { return lflags.map!(s => "-L="~s)().array(); } } dub-0.9.24/source/dub/dependency.d000066400000000000000000000471601267257315000167350ustar00rootroot00000000000000/** Stuff with dependencies. 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, 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; /** Representing a dependency, which is basically a version string and a compare methode, e.g. '>=1.0.0 <2.0.0' (i.e. a space separates the two version numbers) */ struct Dependency { 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; Path m_path; bool m_optional = false; } // A Dependency, which matches every valid version. static @property any() { return Dependency(ANY_IDENT); } static @property invalid() { Dependency ret; ret.m_versA = Version.HEAD; ret.m_versB = Version.RELEASE; return ret; } alias ANY = any; alias INVALID = invalid; this(string ves) { this.versionSpec = ves; } this(in Version ver) { m_inclusiveA = m_inclusiveB = true; m_versA = ver; m_versB = ver; } this(Path path) { this(ANY_IDENT); m_path = path; } @property void path(Path value) { m_path = value; } @property Path path() const { return m_path; } @property bool optional() const { return m_optional; } @property void optional(bool optional) { m_optional = optional; } @property bool isExactVersion() const { return m_versA == m_versB; } @property Version version_() const { enforce(m_versA == m_versB, "Dependency "~versionString~" is no exact version."); return m_versA; } @property string versionString() const { string r; if (this == invalid) return "invalid"; if (m_versA == m_versB && m_inclusiveA && m_inclusiveB) { // Special "==" case if (m_versA == Version.MASTER ) r = "~master"; else r = m_versA.toString(); } else { if (m_versA != Version.RELEASE) r = (m_inclusiveA ? ">=" : ">") ~ m_versA.toString(); if (m_versB != Version.HEAD) r ~= (r.length==0 ? "" : " ") ~ (m_inclusiveB ? "<=" : "<") ~ m_versB.toString(); if (m_versA == Version.RELEASE && m_versB == Version.HEAD) r = ">=0.0.0"; } return r; } @property void versionSpec(string ves) { enforce(ves.length > 0); string orig = ves; 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 <=", 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.RELEASE; m_inclusiveA = true; m_versB = Version(ves); m_inclusiveB = cmpa == "<="; } else if (cmpa == ">=" || cmpa == ">") { m_versA = Version(ves); m_inclusiveA = cmpa == ">="; m_versB = Version.HEAD; 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."); } } } Dependency mapToPath(Path path) const { if (m_path.empty || m_path.absolute) return this; else { Dependency ret = this; ret.path = path ~ ret.path; return ret; } } string toString()() const { auto ret = versionString; if (optional) ret ~= " (optional)"; if (!path.empty) ret ~= " @"~path.toNativeString(); return ret; } Json toJson() const { Json json; if( path.empty && !optional ){ json = Json(this.versionString); } else { json = Json.emptyObject; json["version"] = this.versionString; if (!path.empty) json["path"] = path.toString(); if (optional) json["optional"] = true; } return json; } 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()); } static Dependency fromJson(Json verspec) { 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 = Path(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 specifiy a range of versions. dep = Dependency(ver); } if( auto po = "optional" in verspec ) { dep.optional = verspec.optional.get!bool; } } else { // canonical "package-id": "version" dep = Dependency(verspec.get!string); } return dep; } 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, "path": "path/to/package" } `)); Dependency d = Dependency.ANY; // supposed to ignore the version spec d.optional = true; d.path = Path("path/to/package"); assert(d == parsed); // optional and path not checked by opEquals. assert(d.optional == parsed.optional); assert(d.path == parsed.path); } bool opEquals(in 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; } int opCmp(in 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; } hash_t toHash() const nothrow @trusted { try { auto strhash = &typeid(string).getHash; auto str = this.toString(); return strhash(&str); } catch (Exception) assert(false); } bool valid() const { return m_versA <= m_versB && doCmp(m_inclusiveA && m_inclusiveB, m_versA, m_versB); } bool matches(string vers) const { return matches(Version(vers)); } bool matches(const(Version) v) const { return matches(v); } bool matches(ref const(Version) v) const { if (this == ANY) 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 to versions Dependency merge(ref const(Dependency) o) const { if (this == ANY) return o; if (o == ANY) return this; if (!this.valid || !o.valid) return INVALID; 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; if (this.path != o.path) return INVALID; Version a = m_versA > o.m_versA ? m_versA : o.m_versA; Version b = m_versB < o.m_versB ? m_versB : o.m_versB; Dependency d = this; d.m_inclusiveA = !m_inclusiveA && m_versA >= o.m_versA ? false : o.m_inclusiveA; d.m_versA = a; d.m_inclusiveB = !m_inclusiveB && m_versB <= o.m_versB ? false : o.m_inclusiveB; d.m_versB = b; 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.BRANCH_IDENT) 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 comparision 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).versionString == ">=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).versionString == ">=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).versionString == ">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.MASTER_STRING); assert(a.valid()); assert(a.matches(Version.MASTER)); b = Dependency(Version.MASTER_STRING); m = a.merge(b); assert(m.matches(Version.MASTER)); //assertThrown(a = Dependency(Version.MASTER_STRING ~ " <=1.0.0"), "Construction invalid"); assertThrown(a = Dependency(">=1.0.0 " ~ Version.MASTER_STRING), "Construction invalid"); immutable string branch1 = Version.BRANCH_IDENT ~ "Branch1"; immutable string branch2 = Version.BRANCH_IDENT ~ "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.MASTER), "Dependency(branch1) matches Version.MASTER"); 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"); 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"); a = Dependency("~>3.0.0"); assert(a == Dependency(">=3.0.0 <3.1.0"), "Testing failed: " ~ a.toString()); a = Dependency("~>3.5"); assert(a == Dependency(">=3.5.0 <4.0.0"), "Testing failed: " ~ a.toString()); a = Dependency("~>3.5.0"); assert(a == Dependency(">=3.5.0 <3.6.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); a = Dependency("~>1.0.1-beta"); b = Dependency(">=1.0.1-beta <1.1.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_); b = Dependency(">=1.0.1"); assert(b == a.merge(b)); assert(b == b.merge(a)); logDebug("Dependency Unittest sucess."); } /** A version in the format "major.update.bugfix-prerelease+buildmetadata" according to Semantic Versioning Specification v2.0.0. (deprecated): This also supports a format like "~master", to identify trunk, or "~branch_name" to identify a branch. Both Version types starting with "~" refer to the head revision of the corresponding branch. This is subject to be removed soon. */ struct Version { private { enum MAX_VERS = "99999.0.0"; enum UNKNOWN_VERS = "unknown"; string m_version; } static @property RELEASE() { return Version("0.0.0"); } static @property HEAD() { return Version(MAX_VERS); } static @property MASTER() { return Version(MASTER_STRING); } static @property UNKNOWN() { return Version(UNKNOWN_VERS); } static @property MASTER_STRING() { return "~master"; } static @property BRANCH_IDENT() { return '~'; } this(string vers) { enforce(vers.length > 1, "Version strings must not be empty."); if (vers[0] != BRANCH_IDENT && vers != UNKNOWN_VERS) enforce(vers.isValidVersion(), "Invalid SemVer format: " ~ vers); m_version = vers; } static Version fromString(string vers) { return Version(vers); } bool opEquals(const Version oth) const { if (isUnknown || oth.isUnknown) { throw new Exception("Can't compare unknown versions! (this: %s, other: %s)".format(this, oth)); } return opCmp(oth) == 0; } /// Returns true, if this version indicates a branch, which is not the trunk. @property bool isBranch() const { return !m_version.empty && m_version[0] == BRANCH_IDENT; } @property bool isMaster() const { return m_version == MASTER_STRING; } @property bool isPreRelease() const { if (isBranch) return true; return isPreReleaseVersion(m_version); } @property bool isUnknown() const { return m_version == UNKNOWN_VERS; } /** Comparing Versions is generally possible, but comparing Versions identifying branches other than master will fail. Only equality can be tested for these. */ 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(isMaster ? MAX_VERS : m_version, other.isMaster ? MAX_VERS : other.m_version); } int opCmp(in Version other) const { return opCmp(other); } 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.MASTER_STRING), "Constructing Version("~Version.MASTER_STRING~"') failed"); assert(a.isBranch, "Error: '"~Version.MASTER_STRING~"' treated as branch"); assert(a.isMaster); assert(a == Version.MASTER, "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(Version.MASTER_STRING); 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.RELEASE; 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-0.9.24/source/dub/dependencyresolver.d000066400000000000000000000221141267257315000205070ustar00rootroot00000000000000/** Dependency configuration/version resolution algorithm. Copyright: © 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.dependencyresolver; import dub.dependency; import dub.internal.vibecompat.core.log; import std.algorithm : all, canFind, filter, sort; import std.array : appender, array; import std.conv : to; import std.exception : enforce; import std.string : format, indexOf, lastIndexOf; class DependencyResolver(CONFIGS, CONFIG) { static struct TreeNodes { string pack; CONFIGS configs; hash_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; } } static struct TreeNode { string pack; CONFIG config; hash_t toHash() const nothrow @trusted { size_t ret = typeid(string).getHash(&pack); 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) { static string rootPackage(string p) { auto idx = indexOf(p, ":"); if (idx < 0) return p; return p[0 .. idx]; } auto root_base_pack = rootPackage(root.pack); // find all possible configurations of each possible dependency size_t[string] package_indices; CONFIG[][] all_configs; bool[TreeNode] visited; void findConfigsRec(TreeNode parent, bool parent_unique) { if (parent in visited) return; visited[parent] = true; foreach (ch; getChildren(parent)) { auto basepack = rootPackage(ch.pack); auto pidx = all_configs.length; CONFIG[] configs; if (auto pi = basepack in package_indices) { pidx = *pi; configs = all_configs[*pi]; } else { if (basepack == root_base_pack) configs = [root.config]; else configs = getAllConfigs(basepack); all_configs ~= configs; package_indices[basepack] = pidx; } configs = getSpecificConfigs(ch) ~ configs; // eliminate configurations from which we know that they can't satisfy // the uniquely defined root dependencies (==version or ~branch style dependencies) if (parent_unique) configs = configs.filter!(c => matches(ch.configs, c)).array; all_configs[pidx] = configs; foreach (v; configs) findConfigsRec(TreeNode(ch.pack, v), parent_unique && configs.length == 1); } } findConfigsRec(root, true); // prepend an invalid configuration to denote an unchosen dependency // this is used to properly support optional dependencies (when // getChildren() returns no configurations for an optional dependency, // but getAllConfigs() has already provided an existing list of configs) foreach (ref cfgs; all_configs) cfgs = CONFIG.invalid ~ cfgs; logDebug("Configurations used for dependency resolution:"); foreach (n, i; package_indices) logDebug(" %s (%s): %s", n, i, all_configs[i]); auto config_indices = new size_t[all_configs.length]; config_indices[] = 0; string last_error; visited = null; sizediff_t validateConfigs(TreeNode parent, ref string error) { import std.algorithm : max; if (parent in visited) return -1; visited[parent] = true; sizediff_t maxcpi = -1; sizediff_t parentidx = package_indices.get(rootPackage(parent.pack), -1); auto parentbase = rootPackage(parent.pack); // loop over all dependencies foreach (ch; getChildren(parent)) { auto basepack = rootPackage(ch.pack); assert(basepack in package_indices, format("%s not in packages %s", basepack, package_indices)); // get the current config/version of the current dependency sizediff_t childidx = package_indices[basepack]; if (all_configs[childidx] == [CONFIG.invalid]) { enforce(parentbase != root_base_pack, format("Root package %s contains reference to invalid package %s %s", parent.pack, ch.pack, ch.configs)); // choose another parent config to avoid the invalid child if (parentidx > maxcpi) { error = format("Package %s contains invalid dependency %s", parent.pack, ch.pack); logDiagnostic("%s (ci=%s)", error, parentidx); maxcpi = parentidx; } } else { auto config = all_configs[childidx][config_indices[childidx]]; auto chnode = TreeNode(ch.pack, config); if (config == CONFIG.invalid || !matches(ch.configs, config)) { // if we are at the root level, we can safely skip the maxcpi computation and instead choose another childidx config if (parentbase == root_base_pack) { error = format("No match for dependency %s %s of %s", ch.pack, ch.configs, parent.pack); return childidx; } if (childidx > maxcpi) { maxcpi = max(childidx, parentidx); error = format("Dependency %s -> %s %s mismatches with selected version %s", parent.pack, ch.pack, ch.configs, config); logDebug("%s (ci=%s)", error, maxcpi); } // we know that either the child or the parent needs to be switched // to another configuration, no need to continue with other children if (config == CONFIG.invalid) break; } maxcpi = max(maxcpi, validateConfigs(chnode, error)); } } return maxcpi; } string first_error; while (true) { // check if the current combination of configurations works out visited = null; string error; auto conflict_index = validateConfigs(root, error); if (first_error !is null) first_error = error; // print out current iteration state logDebug("Interation (ci=%s) %s", conflict_index, { import std.array : join; auto cs = new string[all_configs.length]; foreach (p, i; package_indices) { if (all_configs[i].length) cs[i] = p~" "~all_configs[i][config_indices[i]].to!string~(i >= 0 && i >= conflict_index ? " (C)" : ""); else cs[i] = p ~ " [no config]"; } return cs.join(", "); }()); if (conflict_index < 0) { CONFIG[string] ret; foreach (p, i; package_indices) if (all_configs[i].length) { auto cfg = all_configs[i][config_indices[i]]; if (cfg != CONFIG.invalid) ret[p] = cfg; } return ret; } // find the next combination of configurations foreach_reverse (pi, ref i; config_indices) { if (pi > conflict_index) i = 0; else if (++i >= all_configs[pi].length) i = 0; else break; } if (config_indices.all!"a==0") { if (throw_on_failure) throw new Exception("Could not find a valid dependency tree configuration: "~first_error); else return null; } } } protected abstract CONFIG[] getAllConfigs(string pack); protected abstract CONFIG[] getSpecificConfigs(TreeNodes nodes); protected abstract TreeNodes[] getChildren(TreeNode node); protected abstract bool matches(CONFIGS configs, CONFIG config); } unittest { static struct IntConfig { int value; alias value this; enum invalid = IntConfig(-1); } static IntConfig ic(int v) { return IntConfig(v); } static class TestResolver : DependencyResolver!(IntConfig[], 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(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(IntConfig[] 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", [ic(2), ic(1)]), TreeNodes("d", [ic(1)]), TreeNodes("e", [ic(2), ic(1)])], "b:1": [TreeNodes("c", [ic(2), ic(1)]), TreeNodes("d", [ic(1)])], "b:2": [TreeNodes("c", [ic(3), ic(2)]), TreeNodes("d", [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", [ic(1)])], "b:1": [TreeNodes("b", [ic(1)])] ]); assert(res.resolve(TreeNode("a", ic(0))) == ["b":ic(1)]); } } dub-0.9.24/source/dub/description.d000066400000000000000000000046311267257315000171360ustar00rootroot00000000000000/** Types for project descriptions (dub describe). 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.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; alias mainPackage = rootPackage; /// Compatibility alias string configuration; string buildType; string compiler; string[] architecture; string[] platform; PackageDescription[] packages; /// All packages in the dependency tree TargetDescription[] targets; /// Build targets @ignore size_t[string] targetLookup; /// Target index by name /// Targets by name ref inout(TargetDescription) lookupTarget(string name) inout { return targets[ targetLookup[name] ]; } } /** Build settings and meta data of a single package. */ struct PackageDescription { string path; string name; Version version_; 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; string[] lflags; string[] libs; string[] copyFiles; string[] versions; string[] debugVersions; string[] importPaths; string[] stringImportPaths; string[] preGenerateCommands; string[] postGenerateCommands; string[] preBuildCommands; string[] postBuildCommands; @byName BuildRequirement[] buildRequirements; @byName BuildOption[] options; SourceFileDescription[] files; } struct TargetDescription { string rootPackage; string[] packages; string rootConfiguration; BuildSettings buildSettings; string[] dependencies; string[] linkDependencies; } /** Description for a single source file. */ struct SourceFileDescription { @byName SourceFileRole role; alias type = role; /// Compatibility alias string path; } /** Determines */ enum SourceFileRole { unusedStringImport, unusedImport, unusedSource, stringImport, import_, source } dub-0.9.24/source/dub/dub.d000066400000000000000000001126021267257315000153630ustar00rootroot00000000000000/** A package manager. 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, 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.packagesupplier; import dub.project; import dub.generators.generator; import dub.init; // todo: cleanup imports. import std.algorithm; import std.array; import std.conv; import std.datetime; import std.exception; import std.file; import std.process; import std.string; import std.typecons; import std.zip; import std.encoding : sanitize; // Workaround for libcurl liker errors when building with LDC version (LDC) pragma(lib, "curl"); enum defaultRegistryURL = "http://code.dlang.org/"; /// The default supplier for packages, which is the registry /// hosted by code.dlang.org. PackageSupplier[] defaultPackageSuppliers() { logDiagnostic("Using dub registry url '%s'", defaultRegistryURL); return [new RegistryPackageSupplier(URL(defaultRegistryURL))]; } /// Option flags for fetch enum FetchOptions { none = 0, forceBranchUpgrade = 1<<0, usePrerelease = 1<<1, forceRemove = 1<<2, printOnly = 1<<3, } /// The Dub class helps in getting the applications /// dependencies up and running. An instance manages one application. class Dub { private { bool m_dryRun = false; PackageManager m_packageManager; PackageSupplier[] m_packageSuppliers; Path m_rootPath; Path m_tempPath; Path m_userDubPath, m_systemDubPath; Json m_systemConfig, m_userConfig; Path m_projectPath; Project m_project; Path m_overrideSearchPath; } /// Initiales the package manager for the vibe application /// under root. this(PackageSupplier[] additional_package_suppliers = null, string root_path = ".", SkipRegistry skip_registry = SkipRegistry.none) { m_rootPath = Path(root_path); if (!m_rootPath.absolute) m_rootPath = Path(getcwd()) ~ m_rootPath; this(); PackageSupplier[] ps = additional_package_suppliers; if (skip_registry < SkipRegistry.all) { if (auto pp = "registryUrls" in m_userConfig) ps ~= deserializeJson!(string[])(*pp) .map!(url => cast(PackageSupplier)new RegistryPackageSupplier(URL(url))) .array; } if (skip_registry < SkipRegistry.all) { if (auto pp = "registryUrls" in m_systemConfig) ps ~= deserializeJson!(string[])(*pp) .map!(url => cast(PackageSupplier)new RegistryPackageSupplier(URL(url))) .array; } if (skip_registry < SkipRegistry.standard) ps ~= defaultPackageSuppliers(); auto cacheDir = m_userDubPath ~ "cache/"; foreach (p; ps) p.cacheOp(cacheDir, CacheOp.load); m_packageSuppliers = ps; m_packageManager = new PackageManager(m_userDubPath, m_systemDubPath); updatePackageSearchPath(); } /// Initializes DUB with only a single search path this(Path override_path) { this(); m_overrideSearchPath = override_path; m_packageManager = new PackageManager(Path(), Path(), false); updatePackageSearchPath(); } private this() { version(Windows){ m_systemDubPath = Path(environment.get("ProgramData")) ~ "dub/"; m_userDubPath = Path(environment.get("APPDATA")) ~ "dub/"; m_tempPath = Path(environment.get("TEMP")); } else version(Posix){ m_systemDubPath = Path("/var/lib/dub/"); m_userDubPath = Path(environment.get("HOME")) ~ ".dub/"; if(!m_userDubPath.absolute) m_userDubPath = Path(getcwd()) ~ m_userDubPath; m_tempPath = Path("/tmp"); } m_userConfig = jsonFromFile(m_userDubPath ~ "settings.json", true); m_systemConfig = jsonFromFile(m_systemDubPath ~ "settings.json", true); } /// Perform cleanup and persist caches to disk void shutdown() { auto cacheDir = m_userDubPath ~ "cache/"; foreach (p; m_packageSuppliers) p.cacheOp(cacheDir, CacheOp.store); } /// cleans all metadata caches void cleanCaches() { auto cacheDir = m_userDubPath ~ "cache/"; foreach (p; m_packageSuppliers) p.cacheOp(cacheDir, CacheOp.clean); } @property void dryRun(bool v) { m_dryRun = v; } /** Returns the root path (usually the current working directory). */ @property Path rootPath() const { return m_rootPath; } /// ditto @property void rootPath(Path root_path) { m_rootPath = root_path; if (!m_rootPath.absolute) m_rootPath = Path(getcwd()) ~ m_rootPath; } /// Returns the name listed in the dub.json of the current /// application. @property string projectName() const { return m_project.name; } @property Path 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. @property string defaultCompiler() const { if (auto pv = "defaultCompiler" in m_userConfig) if (pv.type == Json.Type.string) return pv.get!string; if (auto pv = "defaultCompiler" in m_systemConfig) if (pv.type == Json.Type.string) return pv.get!string; return .defaultCompiler(); } /// Loads the package from the current working directory as the main /// project package. void loadPackageFromCwd() { loadPackage(m_rootPath); } /// Loads the package from the specified path as the main project package. void loadPackage(Path 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); } void overrideSearchPath(Path path) { if (!path.absolute) path = Path(getcwd()) ~ path; m_overrideSearchPath = path; updatePackageSearchPath(); } string getDefaultConfiguration(BuildPlatform platform, bool allow_non_library_configs = true) const { return m_project.getDefaultConfiguration(platform, allow_non_library_configs); } void upgrade(UpgradeOptions options) { // 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) { try if (m_packageManager.getOrLoadPackage(dep.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) { logDiagnostic("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; if ((options & UpgradeOptions.useCachedResult) && m_project.isUpgradeCacheUpToDate()) { logDiagnostic("Using cached upgrade results..."); versions = m_project.getUpgradeCache(); } else { auto resolver = new DependencyVersionResolver(this, options); versions = resolver.resolve(m_project.rootPackage, m_project.selections); if (options & UpgradeOptions.useCachedResult) { logDiagnostic("Caching upgrade results..."); m_project.setUpgradeCache(versions); } } if (options & UpgradeOptions.printUpgradesOnly) { 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 can be installed 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 can be upgraded from %s to %s.", basename, sver, ver); any = true; } if (any) logInfo("Use \"dub upgrade\" to perform those changes."); return; } foreach (p, ver; versions) { 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, (options & UpgradeOptions.forceRemove) != 0); pack = null; } } FetchOptions fetchOpts; fetchOpts |= (options & UpgradeOptions.preRelease) != 0 ? FetchOptions.usePrerelease : FetchOptions.none; fetchOpts |= (options & UpgradeOptions.forceRemove) != 0 ? FetchOptions.forceRemove : FetchOptions.none; if (!pack) fetch(p, ver, defaultPlacementLocation, fetchOpts, "getting selected version"); if ((options & UpgradeOptions.select) && ver.path.empty && p != m_project.rootPackage.name) m_project.selections.selectVersion(p, ver.version_); } m_project.reinit(); if (options & UpgradeOptions.select) m_project.saveSelections(); } /// Generate project files for a specified IDE. /// 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, Path custom_main_file) { if (custom_main_file.length && !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.length) 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("__test__%s__", config); BuildSettings lbuildsettings = settings.buildSettings; m_project.addBuildSettings(lbuildsettings, settings.platform, config, null, true); if (lbuildsettings.targetType == TargetType.none) { logInfo(`Configuration '%s' has target type "none". Skipping test.`, config); return; } if (lbuildsettings.targetType == TargetType.executable) { if (config == "unittest") logInfo("Running custom 'unittest' configuration.", config); else logInfo(`Configuration '%s' does not output a library. Falling back to "dub -b unittest -c %s".`, config, 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 { logInfo(`Generating test runner configuration '%s' for '%s' (%s).`, test_config, config, lbuildsettings.targetType); BuildSettingsTemplate tcinfo = m_project.rootPackage.info.getConfiguration(config).buildSettings; tcinfo.targetType = TargetType.executable; tcinfo.targetName = test_config; tcinfo.versions[""] ~= "VibeCustomMain"; // HACK for vibe.d's legacy main() behavior string custommodname; if (custom_main_file.length) { 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.toString().baseName(".d"); } string[] import_modules; foreach (file; lbuildsettings.sourceFiles) { if (file.endsWith(".d") && Path(file).head.toString() != "package.d") import_modules ~= lbuildsettings.determineModuleName(Path(file), m_project.rootPackage.path); } // generate main file Path 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.info.configurations ~= ConfigurationInfo(test_config, tcinfo); m_project = new Project(m_packageManager, m_project.rootPackage); settings.config = test_config; } generator.generate(settings); } /// Outputs a JSON description of the project, including its dependencies. deprecated void describeProject(BuildPlatform platform, string config) { import std.stdio; auto desc = m_project.describe(platform, config); writeln(desc.serializeToPrettyJson()); } void listImportPaths(BuildPlatform platform, string config, string buildType, bool nullDelim) { import std.stdio; foreach(path; m_project.listImportPaths(platform, config, buildType, nullDelim)) { writeln(path); } } void listStringImportPaths(BuildPlatform platform, string config, string buildType, bool nullDelim) { import std.stdio; foreach(path; m_project.listStringImportPaths(platform, config, buildType, nullDelim)) { writeln(path); } } void listProjectData(BuildPlatform platform, string config, string buildType, string[] requestedData, Compiler formattingCompiler, bool nullDelim) { 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(platform, config, buildType, requestedDataSplit, formattingCompiler, nullDelim); write( data.joiner(nullDelim? "\0" : newline) ); if(!nullDelim) writeln(); } /// Cleans intermediate/cache files of the given package void cleanPackage(Path 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()); } /// Returns all cached packages as a "packageId" = "version" associative array string[string] cachedPackages() const { return m_project.cachedPackagesIDs; } /// 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 = "") { Json pinfo; PackageSupplier supplier; foreach(ps; m_packageSuppliers){ try { pinfo = ps.getPackageDescription(packageId, dep, (options & FetchOptions.usePrerelease) != 0); supplier = ps; break; } catch(Exception e) { logDiagnostic("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; Path placement; final switch (location) { case PlacementLocation.local: placement = m_rootPath; break; case PlacementLocation.user: placement = m_userDubPath ~ "packages/"; break; case PlacementLocation.system: placement = m_systemDubPath ~ "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.vers != ver) logInfo("A new version for %s is available (%s -> %s). Run \"dub upgrade %s\" to switch.", packageId, existing.vers, 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, (options & FetchOptions.forceRemove) != 0); } } if (reason.length) logInfo("Fetching %s %s (%s)...", packageId, ver, reason); else logInfo("Fetching %s %s...", packageId, ver); if (m_dryRun) return null; logDiagnostic("Acquiring package zip file"); auto dload = m_projectPath ~ ".dub/temp/downloads"; auto tempfname = packageId ~ "-" ~ (ver.startsWith('~') ? ver[1 .. $] : ver) ~ ".zip"; auto tempFile = m_tempPath ~ tempfname; string sTempFile = tempFile.toNativeString(); if (exists(sTempFile)) std.file.remove(sTempFile); supplier.retrievePackage(tempFile, packageId, dep, (options & FetchOptions.usePrerelease) != 0); // Q: continue on fail? scope(exit) std.file.remove(sTempFile); logInfo("Placing %s %s to %s...", packageId, ver, placement.toNativeString()); auto clean_package_version = ver[ver.startsWith("~") ? 1 : 0 .. $]; clean_package_version = clean_package_version.replace("+", "_"); // + has special meaning for Optlink Path dstpath = placement ~ (packageId ~ "-" ~ clean_package_version); return m_packageManager.storeFetchedPackage(tempFile, pinfo, dstpath); } /// Removes a given package from the list of present/cached modules. /// @removeFromApplication: if true, this will also remove an entry in the /// list of dependencies in the application's dub.json void remove(in Package pack, bool force_remove) { logInfo("Removing %s in %s", pack.name, pack.path.toNativeString()); if (!m_dryRun) m_packageManager.remove(pack, force_remove); } /// @see remove(string, string, RemoveLocation) enum RemoveVersionWildcard = "*"; /// This will remove a given package with a specified version from the /// location. /// It will remove at most one package, unless @param version_ is /// specified as wildcard "*". /// @param package_id Package to be removed /// @param version_ Identifying a version or a wild card. An empty string /// may be passed into. In this case 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. /// Note: as wildcard string only RemoveVersionWildcard ("*") is supported. /// @param location_ void remove(string package_id, string version_, PlacementLocation location_, bool force_remove) { 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; const bool wildcardOrEmpty = version_ == RemoveVersionWildcard || version_.empty; // Retrieve packages to be removed. foreach(pack; m_packageManager.getPackageIterator(package_id)) if ((wildcardOrEmpty || pack.vers == version_) && 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 ~ "', version: '" ~ version_ ~ "', location: '" ~ to!string(location_) ~ "'" ~ ")"); } 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.vers); throw new Exception("Please specify a individual version using --version=... or use the" ~ " wildcard --version=" ~ RemoveVersionWildcard ~ " to remove all versions."); } logDebug("Removing %s packages.", packages.length); foreach(pack; packages) { try { remove(pack, force_remove); logInfo("Removed %s, version %s.", package_id, pack.vers); } catch (Exception e) { logError("Failed to remove %s %s: %s", package_id, pack.vers, e.msg); logInfo("Continuing with other packages (if any)."); } } } void addLocalPackage(string path, string ver, bool system) { if (m_dryRun) return; m_packageManager.addLocalPackage(makeAbsolute(path), ver, system ? LocalPackageType.system : LocalPackageType.user); } void removeLocalPackage(string path, bool system) { if (m_dryRun) return; m_packageManager.removeLocalPackage(makeAbsolute(path), system ? LocalPackageType.system : LocalPackageType.user); } void addSearchPath(string path, bool system) { if (m_dryRun) return; m_packageManager.addSearchPath(makeAbsolute(path), system ? LocalPackageType.system : LocalPackageType.user); } void removeSearchPath(string path, bool system) { if (m_dryRun) return; m_packageManager.removeSearchPath(makeAbsolute(path), system ? LocalPackageType.system : LocalPackageType.user); } void createEmptyPackage(Path path, string[] deps, string type, PackageFormat format = PackageFormat.sdl) { if (!path.absolute) path = m_rootPath ~ path; path.normalize(); if (m_dryRun) return; string[string] depVers; string[] notFound; // keep track of any failed packages in here foreach(ps; this.m_packageSuppliers){ foreach(dep; deps){ try{ auto versionStrings = ps.getVersions(dep); depVers[dep] = versionStrings[$-1].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)); } initPackage(path, depVers, type, format); //Act smug to the user. logInfo("Successfully created an empty project in '%s'.", path.toNativeString()); } void runDdox(bool run) { if (m_dryRun) return; auto ddox_pack = m_packageManager.getBestPackage("ddox", ">=0.0.0"); if (!ddox_pack) ddox_pack = m_packageManager.getBestPackage("ddox", "~master"); if (!ddox_pack) { logInfo("DDOX is not present, getting it and storing user wide"); ddox_pack = fetch("ddox", Dependency(">=0.0.0"), defaultPlacementLocation, FetchOptions.none); } version(Windows) auto ddox_exe = "ddox.exe"; else auto ddox_exe = "ddox"; if( !existsFile(ddox_pack.path~ddox_exe) ){ logInfo("DDOX in %s is not built, performing build now.", ddox_pack.path.toNativeString()); auto ddox_dub = new Dub(m_packageSuppliers); ddox_dub.loadPackage(ddox_pack.path); ddox_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); settings.buildType = "debug"; ddox_dub.generateProject("build", settings); //runCommands(["cd "~ddox_pack.path.toNativeString()~" && dub build -v"]); } auto p = ddox_pack.path; p.endsWithSlash = true; auto dub_path = p.toNativeString(); string[] commands; string[] filterargs = m_project.rootPackage.info.ddoxFilterArgs.dup; if (filterargs.empty) filterargs = ["--min-protection=Protected", "--only-documented"]; commands ~= dub_path~"ddox filter "~filterargs.join(" ")~" docs.json"; if (!run) { commands ~= dub_path~"ddox generate-html --navigation-type=ModuleTree docs.json docs"; version(Windows) commands ~= "xcopy /S /D "~dub_path~"public\\* docs\\"; else commands ~= "rsync -ru '"~dub_path~"public/' docs/"; } runCommands(commands); if (run) { auto proc = spawnProcess([dub_path~"ddox", "serve-html", "--navigation-type=ModuleTree", "docs.json", "--web-file-dir="~dub_path~"public"]); browse("http://127.0.0.1:8080/"); wait(proc); } } private void updatePackageSearchPath() { if (m_overrideSearchPath.length) { m_packageManager.disableDefaultSearchPaths = true; m_packageManager.searchPath = [m_overrideSearchPath]; } else { auto p = environment.get("DUBPATH"); Path[] paths; version(Windows) enum pathsep = ";"; else enum pathsep = ":"; if (p.length) paths ~= p.split(pathsep).map!(p => Path(p))().array(); m_packageManager.disableDefaultSearchPaths = false; m_packageManager.searchPath = paths; } } private Path makeAbsolute(Path p) const { return p.absolute ? p : m_rootPath ~ p; } private Path makeAbsolute(string p) const { return makeAbsolute(Path(p)); } } string determineModuleName(BuildSettings settings, Path file, Path base_path) { assert(base_path.absolute); if (!file.absolute) file = base_path ~ file; size_t path_skip = 0; foreach (ipath; settings.importPaths.map!(p => Path(p))) { if (!ipath.absolute) ipath = base_path ~ ipath; assert(!ipath.empty); if (file.startsWith(ipath) && ipath.length > path_skip) path_skip = ipath.length; } enforce(path_skip > 0, format("Source file '%s' not found in any import path.", file.toNativeString())); auto mpath = file[path_skip .. file.length]; 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].toString(); 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])))*\*+/)|(//.*)`, "g"); module_pattern = regex(`module\s+([\w\.]+)\s*;`, "g"); regex_initialized = true; } content = replaceAll(content, comments_pattern, ""); auto result = matchFirst(content, module_pattern); string moduleName; if(!result.empty) moduleName = result.front; if (moduleName.length >= 7) moduleName = moduleName[7..$-1]; return moduleName; } unittest { //test empty string string name = getModuleNameFromContent(""); assert(name == "", "can't get module name from empty string"); //test simple name name = getModuleNameFromContent("module myPackage.myModule;"); assert(name == "myPackage.myModule", "can't parse module name"); //test if it can ignore module inside comments name = getModuleNameFromContent("/** module fakePackage.fakeModule; */ module myPackage.myModule;"); assert(name == "myPackage.myModule", "can't parse module name"); name = getModuleNameFromContent("//module fakePackage.fakeModule; module myPackage.myModule;"); assert(name == "myPackage.myModule", "can't parse module name"); } /** * Search for module keyword in file */ string getModuleNameFromFile(string filePath) { string fileContent = filePath.readText; logDiagnostic("Get module name from path: " ~ filePath); return getModuleNameFromContent(fileContent); } enum UpgradeOptions { none = 0, upgrade = 1<<1, /// Upgrade existing packages preRelease = 1<<2, /// inclde pre-release versions in upgrade forceRemove = 1<<3, /// Force removing package folders, which contain unknown files select = 1<<4, /// Update the dub.selections.json file with the upgraded versions printUpgradesOnly = 1<<5, /// Instead of downloading new packages, just print a message to notify the user of their existence useCachedResult = 1<<6, /// Use cached information stored with the package to determine upgrades } enum SkipRegistry { none, standard, all } 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; } this(Dub dub, UpgradeOptions options) { m_dub = dub; m_options = options; } Dependency[string] resolve(Package root, SelectedVersions selected_versions) { m_rootPackage = root; m_selectedVersions = selected_versions; return super.resolve(TreeNode(root.name, Dependency(root.ver)), (m_options & UpgradeOptions.printUpgradesOnly) == 0); } protected override Dependency[] getAllConfigs(string pack) { if (auto pvers = pack in m_packageVersions) return *pvers; if (!(m_options & UpgradeOptions.upgrade) && 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.ver; 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) { logDebug("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; if (!versions.length) logDiagnostic("Nothing found for %s", pack); auto ret = versions.map!(v => Dependency(v)).array; m_packageVersions[pack] = ret; return ret; } protected override Dependency[] getSpecificConfigs(TreeNodes nodes) { if (!nodes.configs.path.empty) return [nodes.configs]; else return null; } protected override TreeNodes[] getChildren(TreeNode node) { 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 (dname, dspec; pack.dependencies) { auto dbasename = getBasePackageName(dname); // detect dependencies to the root package (or sub packages thereof) if (dbasename == basepack.name) { auto absdeppath = dspec.mapToPath(pack.path).path; absdeppath.endsWithSlash = true; auto subpack = m_dub.m_packageManager.getSubPackage(basepack, getSubPackageName(dname), true); if (subpack) { auto desireddeppath = dname == dbasename ? basepack.path : subpack.path; desireddeppath.endsWithSlash = true; enforce(dspec.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(dname, node.config); continue; } if (dspec.optional && !m_dub.packageManager.getFirstPackage(dname)) continue; if (m_options & UpgradeOptions.upgrade || !m_selectedVersions || !m_selectedVersions.hasSelectedVersion(dbasename)) ret ~= TreeNodes(dname, dspec.mapToPath(pack.path)); else ret ~= TreeNodes(dname, m_selectedVersions.getSelectedVersion(dbasename)); } 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 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, 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; } } if (!dep.path.empty) { try { auto ret = m_dub.packageManager.getOrLoadPackage(dep.path); if (dep.matches(ret.ver)) 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.getPackageDescription(name, dep, prerelease); 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; fetchOpts |= (m_options & UpgradeOptions.forceRemove) != 0 ? FetchOptions.forceRemove : FetchOptions.none; m_dub.fetch(rootpack, dep, 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; } } dub-0.9.24/source/dub/generators/000077500000000000000000000000001267257315000166135ustar00rootroot00000000000000dub-0.9.24/source/dub/generators/build.d000066400000000000000000000516231267257315000200660ustar00rootroot00000000000000/** 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.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; version(Windows) enum objSuffix = ".obj"; else enum objSuffix = ".o"; class BuildGenerator : ProjectGenerator { private { PackageManager m_packageMan; Path[] m_temporaryFiles; } this(Project project) { super(project); m_packageMan = project.packageManager; } override void generateTargets(GeneratorSettings settings, in TargetInfo[string] targets) { scope (exit) cleanupTemporaries(); logInfo("Performing \"%s\" build using %s for %-(%s, %).", settings.buildType, settings.platform.compilerBinary, settings.platform.architecture); bool any_cached = false; 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); Path[] additional_dep_files; auto bs = ti.buildSettings.dup; foreach (ldep; ti.linkDependencies) { auto dbs = targets[ldep].buildSettings; if (bs.targetType != TargetType.staticLibrary) { bs.addSourceFiles((Path(dbs.targetPath) ~ getTargetFileName(dbs, settings.platform)).toNativeString()); } else { additional_dep_files ~= Path(dbs.targetPath) ~ getTargetFileName(dbs, settings.platform); } } if (buildTarget(settings, bs, ti.pack, ti.config, ti.packages, additional_dep_files)) any_cached = true; } // build all targets auto root_ti = targets[m_project.rootPackage.name]; 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 buildTarget(settings, root_ti.buildSettings.dup, m_project.rootPackage, root_ti.config, root_ti.packages, null); } 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; if (settings.run && !(buildsettings.options & BuildOption.syntaxOnly)) { auto exe_file_path = Path(buildsettings.targetPath) ~ 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 Path[] additional_dep_files) { auto cwd = Path(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) { auto p = Path(path); // storing in a separate temprary to work around #601 auto prel = p.absolute ? p.relativeTo(cwd) : p; return prel.toNativeString(); } 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); else if (settings.direct || !generate_binary) performDirectBuild(settings, buildsettings, pack, config); else cached = performCachedBuild(settings, buildsettings, pack, config, build_id, packages, additional_dep_files); // run post-build commands if (!cached && buildsettings.postBuildCommands.length) { logInfo("Running post-build commands..."); runBuildCommands(buildsettings.postBuildCommands, pack, settings, buildsettings); } return cached; } bool performCachedBuild(GeneratorSettings settings, BuildSettings buildsettings, in Package pack, string config, string build_id, in Package[] packages, in Path[] additional_dep_files) { auto cwd = Path(getcwd()); auto target_path = pack.path ~ format(".dub/build/%s/", build_id); if (!settings.force && isUpToDate(target_path, buildsettings, settings.platform, pack, packages, additional_dep_files)) { logInfo("%s %s: target for configuration \"%s\" is up to date.", pack.name, pack.vers, config); logDiagnostic("Using existing build in %s.", target_path.toNativeString()); copyTargetFile(target_path, buildsettings, settings.platform); return true; } if (settings.tempBuild || !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); return false; } // determine basic build properties auto generate_binary = !(buildsettings.options & BuildOption.syntaxOnly); logInfo("%s %s: building configuration \"%s\"...", pack.name, pack.vers, config); if( buildsettings.preBuildCommands.length ){ logInfo("Running pre-build commands..."); runBuildCommands(buildsettings.preBuildCommands, pack, settings, buildsettings); } // override target path auto cbuildsettings = buildsettings; cbuildsettings.targetPath = target_path.relativeTo(cwd).toNativeString(); buildWithCompiler(settings, cbuildsettings); copyTargetFile(target_path, buildsettings, settings.platform); return false; } void performRDMDBuild(GeneratorSettings settings, ref BuildSettings buildsettings, in Package pack, string config) { auto cwd = Path(getcwd()); //Added check for existance of [AppNameInPackagejson].d //If exists, use that as the starting file. Path mainsrc; if (buildsettings.mainSourceFile.length) { mainsrc = Path(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, 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 "\" Path exe_file_path; bool tmp_target = false; if (generate_binary) { if (settings.tempBuild || (settings.run && !isWritableDir(Path(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; } exe_file_path = Path(buildsettings.targetPath) ~ getTargetFileName(buildsettings, settings.platform); settings.compiler.setTarget(buildsettings, settings.platform); } logDiagnostic("Application output name is '%s'", 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.vers, 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 ~= exe_file_path; foreach (f; buildsettings.copyFiles) m_temporaryFiles ~= Path(buildsettings.targetPath).parentPath ~ Path(f).head; } } void performDirectBuild(GeneratorSettings settings, ref BuildSettings buildsettings, in Package pack, string config) { auto cwd = Path(getcwd()); auto generate_binary = !(buildsettings.options & BuildOption.syntaxOnly); auto is_static_library = buildsettings.targetType == TargetType.staticLibrary || buildsettings.targetType == TargetType.library; // make file paths relative to shrink the command line foreach (ref f; buildsettings.sourceFiles) { auto fp = Path(f); if( fp.absolute ) fp = fp.relativeTo(cwd); f = fp.toNativeString(); } logInfo("%s %s: building configuration \"%s\"...", pack.name, pack.vers, config); // make all target/import paths relative string makeRelative(string path) { auto p = Path(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); Path exe_file_path; bool is_temp_target = false; if (generate_binary) { if (settings.tempBuild || (settings.run && !isWritableDir(Path(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; } exe_file_path = Path(buildsettings.targetPath) ~ getTargetFileName(buildsettings, settings.platform); } if( buildsettings.preBuildCommands.length ){ logInfo("Running pre-build commands..."); runBuildCommands(buildsettings.preBuildCommands, pack, settings, buildsettings); } buildWithCompiler(settings, buildsettings); if (is_temp_target) { m_temporaryFiles ~= exe_file_path; foreach (f; buildsettings.copyFiles) m_temporaryFiles ~= Path(buildsettings.targetPath).parentPath ~ Path(f).head; } } private string computeBuildID(string config, in BuildSettings buildsettings, GeneratorSettings settings) { import std.digest.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(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(Path build_path, BuildSettings buildsettings, BuildPlatform platform) { auto filename = getTargetFileName(buildsettings, platform); auto src = build_path ~ filename; logDiagnostic("Copying target from %s to %s", src.toNativeString(), buildsettings.targetPath); if (!existsFile(Path(buildsettings.targetPath))) mkdirRecurse(buildsettings.targetPath); hardLinkFile(src, Path(buildsettings.targetPath) ~ filename, true); } private bool isUpToDate(Path target_path, BuildSettings buildsettings, BuildPlatform platform, in Package main_pack, in Package[] packages, in Path[] additional_dep_files) { import std.datetime; auto targetfile = target_path ~ getTargetFileName(buildsettings, 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; // TODO: add library files foreach (p; packages) allfiles ~= (p.packageInfoFilename != Path.init ? p : p.basePackage).packageInfoFilename.toNativeString(); foreach (f; additional_dep_files) allfiles ~= f.toNativeString(); if (main_pack is m_project.rootPackage) allfiles ~= (main_pack.path ~ SelectedVersions.defaultFile).toNativeString(); foreach (file; allfiles.data) { if (!existsFile(file)) { logDiagnostic("File %s doesn't exists, 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(string path) { import std.path : buildNormalizedPath, dirSeparator, stripDrive; return stripDrive(buildNormalizedPath(getcwd(), path~objSuffix))[1..$].replace(dirSeparator, "."); } /// Compile a single source file (srcFile), and write the object to objName. static string compileUnit(string srcFile, string objName, BuildSettings bs, GeneratorSettings gs) { Path tempobj = Path(bs.targetPath)~objName; string objPath = tempobj.toNativeString(); bs.libs = null; bs.lflags = null; bs.sourceFiles = [ srcFile ]; bs.targetType = TargetType.object; gs.compiler.prepareBuildSettings(bs, BuildSetting.commandLine); gs.compiler.setTarget(bs, gs.platform, objPath); gs.compiler.invoke(bs, gs.platform, gs.compileCallback); return objPath; } 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; Path target_file; scope (failure) { logDiagnostic("FAIL %s %s %s" , buildsettings.targetPath, buildsettings.targetName, buildsettings.targetType); auto tpath = Path(buildsettings.targetPath) ~ getTargetFileName(buildsettings, settings.platform); 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(f)); auto objs = new string[](srcs.walkLength); void compileSource(size_t i, string src) { logInfo("Compiling %s...", src); objs[i] = compileUnit(src, pathToObjName(src), 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=> f.isLinkerFile()).array; settings.compiler.setTarget(lbuildsettings, settings.platform); settings.compiler.prepareBuildSettings(lbuildsettings, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles); settings.compiler.invokeLinker(lbuildsettings, settings.platform, objs, settings.linkCallback); /* NOTE: for DMD experimental separate compile/link is used, but this is not yet implemented on the other compilers. Later this should be integrated somehow in the build process (either in the dub.json, or using a command line flag) */ } else if (settings.buildMode == BuildMode.allAtOnce || settings.platform.compilerBinary != "dmd" || !generate_binary || is_static_library) { // setup for command line if (generate_binary) settings.compiler.setTarget(buildsettings, settings.platform); settings.compiler.prepareBuildSettings(buildsettings, BuildSetting.commandLine); // don't include symbols of dependencies (will be included by the top level target) if (is_static_library) buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(f => !f.isLinkerFile()).array; // invoke the compiler settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback); } else { // determine path for the temporary object file string tempobjname = buildsettings.targetName ~ objSuffix; Path tempobj = Path(buildsettings.targetPath) ~ tempobjname; // setup linker command line auto lbuildsettings = buildsettings; lbuildsettings.sourceFiles = lbuildsettings.sourceFiles.filter!(f => isLinkerFile(f)).array; settings.compiler.setTarget(lbuildsettings, settings.platform); settings.compiler.prepareBuildSettings(lbuildsettings, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles); // setup compiler command line buildsettings.libs = null; buildsettings.lflags = null; buildsettings.addDFlags("-c", "-of"~tempobj.toNativeString()); buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(f => !isLinkerFile(f)).array; settings.compiler.prepareBuildSettings(buildsettings, BuildSetting.commandLine); settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback); logInfo("Linking..."); settings.compiler.invokeLinker(lbuildsettings, settings.platform, [tempobj.toNativeString()], settings.linkCallback); } } void runTarget(Path exe_file_path, in BuildSettings buildsettings, string[] run_args, GeneratorSettings settings) { if (buildsettings.targetType == TargetType.executable) { auto cwd = Path(getcwd()); auto runcwd = cwd; if (buildsettings.workingDirectory.length) { runcwd = Path(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; } 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); } else { auto prg_pid = spawnProcess(exe_path_string ~ run_args); auto result = prg_pid.wait(); enforce(result == 0, "Program exited with code "~to!string(result)); } } else enforce(false, "Target is a library. Skipping execution."); } 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 Path 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"; } unittest { version (Windows) { assert(isLinkerFile("test.obj")); assert(isLinkerFile("test.lib")); assert(isLinkerFile("test.res")); assert(!isLinkerFile("test.o")); assert(!isLinkerFile("test.d")); } else { assert(isLinkerFile("test.o")); assert(isLinkerFile("test.a")); assert(isLinkerFile("test.so")); assert(isLinkerFile("test.dylib")); assert(!isLinkerFile("test.obj")); assert(!isLinkerFile("test.d")); } } dub-0.9.24/source/dub/generators/cmake.d000066400000000000000000000113711267257315000200430ustar00rootroot00000000000000/** 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; Path projectRoot = m_project.rootPackage.path; Path 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)); if(addTarget) { script.put("add_%s(%s %s\n".format(targetType, name, libType)); foreach(file; info.buildSettings.sourceFiles) script.put(" %s\n".format(file)); script.put(")\n"); script.put( "target_link_libraries(%s %s %s)\n".format( name, (info.dependencies ~ info.linkDependencies).dup.stdsort.uniq.map!sanitize.join(" "), info.buildSettings.libs.dup.join(" ") ) ); script.put( `set_target_properties(%s PROPERTIES TEXT_INCLUDE_DIRECTORIES "%s")`.format( name, info.buildSettings.stringImportPaths.dup.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. string sanitize(string name) { return name.replace(":", "_"); } dub-0.9.24/source/dub/generators/generator.d000066400000000000000000000427231267257315000207560ustar00rootroot00000000000000/** Generator for 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.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; } this(Project project) { m_project = project; } /** Performs the full generator process. */ final void generate(GeneratorSettings settings) { if (!settings.config.length) settings.config = m_project.getDefaultConfiguration(settings.platform); TargetInfo[string] targets; string[string] configs = m_project.getPackageConfigs(settings.platform, settings.config); foreach (pack; m_project.getTopologicalPackageList(true, null, configs)) { BuildSettings buildsettings; buildsettings.processVars(m_project, pack, pack.getBuildSettings(settings.platform, configs[pack.name]), true); prepareGeneration(pack, settings, buildsettings); } string[] mainfiles; collect(settings, m_project.rootPackage, targets, configs, mainfiles, null); downwardsInheritSettings(m_project.rootPackage.name, targets, targets[m_project.rootPackage.name].buildSettings); foreach (ref t; targets.byValue) enforceBuildRequirements(t.buildSettings); auto bs = &targets[m_project.rootPackage.name].buildSettings; if (bs.targetType == TargetType.executable) bs.addSourceFiles(mainfiles); 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]), true); bool generate_binary = !(buildsettings.options & BuildOption.syntaxOnly); finalizeGeneration(pack, settings, buildsettings, Path(bs.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) {} private BuildSettings collect(GeneratorSettings settings, Package pack, ref TargetInfo[string] targets, in string[string] configs, ref string[] main_files, string bin_pack) { if (auto pt = pack.name in targets) return pt.buildSettings; // determine the actual target type auto shallowbs = pack.getBuildSettings(settings.platform, configs[pack.name]); TargetType tt = shallowbs.targetType; if (pack is m_project.rootPackage) { if (tt == TargetType.autodetect || tt == TargetType.library) tt = TargetType.staticLibrary; } else { if (tt == TargetType.autodetect || tt == TargetType.library) tt = settings.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 && shallowbs.sourceFiles.empty) { logWarn(`Configuration '%s' of package %s contains no source files. Please add {"targetType": "none"} to it's package description to avoid building it.`, configs[pack.name], pack.name); tt = TargetType.none; } shallowbs.targetType = tt; bool generates_binary = tt != TargetType.sourceLibrary && tt != TargetType.none; bool is_target = generates_binary || pack is m_project.rootPackage; if (tt == TargetType.none) { // ignore any build settings for targetType none (only dependencies will be processed) shallowbs = BuildSettings.init; } // start to build up the build settings BuildSettings buildsettings; if (is_target) buildsettings = settings.buildSettings.dup; processVars(buildsettings, m_project, pack, shallowbs, true); // remove any mainSourceFile from library builds if (buildsettings.targetType != TargetType.executable && buildsettings.mainSourceFile.length) { buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(f => f != buildsettings.mainSourceFile)().array; main_files ~= buildsettings.mainSourceFile; } logDiagnostic("Generate target %s (%s %s %s)", pack.name, buildsettings.targetType, buildsettings.targetPath, buildsettings.targetName); if (is_target) targets[pack.name] = TargetInfo(pack, [pack], configs[pack.name], buildsettings, null); foreach (depname; pack.dependencies.byKey.array.sort()) { auto depspec = pack.dependencies[depname]; if (!pack.hasDependency(depname, configs[pack.name])) continue; auto dep = m_project.getDependency(depname, depspec.optional); if (!dep) continue; auto depbs = collect(settings, dep, targets, configs, main_files, is_target ? pack.name : bin_pack); if (depbs.targetType != TargetType.sourceLibrary && depbs.targetType != TargetType.none) { // add a reference to the target binary and remove all source files in the dependency build settings depbs.sourceFiles = depbs.sourceFiles.filter!(f => f.isLinkerFile()).array; depbs.importFiles = null; } buildsettings.add(depbs); if (depbs.targetType == TargetType.executable) continue; auto pt = (is_target ? pack.name : bin_pack) in targets; assert(pt !is null); if (auto pdt = depname in targets) { pt.dependencies ~= depname; pt.linkDependencies ~= depname; if (depbs.targetType == TargetType.staticLibrary) pt.linkDependencies = pt.linkDependencies.filter!(d => !pdt.linkDependencies.canFind(d)).array ~ pdt.linkDependencies; } else pt.packages ~= dep; } if (is_target) { // add build type settings and convert plain DFLAGS to build options m_project.addBuildTypeSettings(buildsettings, settings.platform, settings.buildType); settings.compiler.extractBuildOptions(buildsettings); enforce (generates_binary || pack !is m_project.rootPackage || (buildsettings.options & BuildOption.syntaxOnly), format("Main package must have a binary target type, not %s. Cannot build.", tt)); targets[pack.name].buildSettings = buildsettings.dup; } return buildsettings; } private string[] downwardsInheritSettings(string target, TargetInfo[string] targets, in BuildSettings root_settings) { auto ti = &targets[target]; ti.buildSettings.addVersions(root_settings.versions); ti.buildSettings.addDebugVersions(root_settings.debugVersions); ti.buildSettings.addOptions(root_settings.options); // special support for overriding string imports in parent packages // this is a candidate for deprecation, once an alternative approach // has been found if (ti.buildSettings.stringImportPaths.length) { // override string import files (used for up to date checking) foreach (ref f; ti.buildSettings.stringImportFiles) foreach (fi; root_settings.stringImportFiles) if (f != fi && Path(f).head == Path(fi).head) { f = fi; } // add the string import paths (used by the compiler to find the overridden files) ti.buildSettings.prependStringImportPaths(root_settings.stringImportPaths); } string[] packs = ti.packages.map!(p => p.name).array; foreach (d; ti.dependencies) packs ~= downwardsInheritSettings(d, targets, root_settings); logDebug("%s: %s", target, packs); // Add Have_* versions *after* downwards inheritance, so that dependencies // are build independently of the parent packages w.r.t the other parent // dependencies. This enables sharing of the same package build for // multiple dependees. ti.buildSettings.addVersions(packs.map!(pn => "Have_" ~ stripDlangSpecialChars(pn)).array); return packs; } } struct GeneratorSettings { BuildPlatform platform; Compiler compiler; string config; string buildType; BuildSettings buildSettings; BuildMode buildMode = BuildMode.separate; bool combined; // compile all in one go instead of each dependency separately // only used for generator "build" bool run, force, direct, clean, rdmd, tempBuild, parallelBuild; 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 GeneratorSettings settings, in BuildSettings buildsettings) { if (buildsettings.preGenerateCommands.length) { logInfo("Running pre-generate commands for %s...", pack.name); runBuildCommands(buildsettings.preGenerateCommands, pack, settings, buildsettings); } } /** Runs post-build commands and copies required files to the binary directory. */ private void finalizeGeneration(in Package pack, in GeneratorSettings settings, in BuildSettings buildsettings, Path target_path, bool generate_binary) { if (buildsettings.postGenerateCommands.length) { logInfo("Running post-generate commands for %s...", pack.name); runBuildCommands(buildsettings.postGenerateCommands, pack, settings, buildsettings); } if (generate_binary) { if (!exists(buildsettings.targetPath)) mkdirRecurse(buildsettings.targetPath); if (buildsettings.copyFiles.length) { void copyFolderRec(Path folder, Path 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 = Path(file); if (!src.absolute) src = pack.path ~ src; auto dst = target_path ~ Path(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 = Path(file); if (!src.absolute) src = pack.path ~ src; auto dst = target_path ~ Path(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; } } } } } } } void runBuildCommands(in string[] commands, in Package pack, in GeneratorSettings settings, in BuildSettings build_settings) { import std.conv; import std.process; import dub.internal.utils; 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_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_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_COMBINED"] = settings.combined? "TRUE" : ""; env["DUB_RUN"] = settings.run? "TRUE" : ""; env["DUB_FORCE"] = settings.force? "TRUE" : ""; env["DUB_DIRECT"] = settings.direct? "TRUE" : ""; env["DUB_CLEAN"] = settings.clean? "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(" "); runCommands(commands, env); } dub-0.9.24/source/dub/generators/sublimetext.d000066400000000000000000000053131267257315000213270ustar00rootroot00000000000000/** 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.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!targetFolderJson.array.Json, "build_systems": buildSystems(settings.platform), ]); auto jsonString = appender!string(); writePrettyJsonString(jsonString, root); string projectPath = m_project.name ~ ".sublime-project"; write(projectPath, jsonString.data); logInfo("Project '%s' generated.", projectPath); } } Json targetFolderJson(in ProjectGenerator.TargetInfo target) { return [ "name": target.pack.name.Json, "path": target.pack.path.toNativeString.Json, "follow_symlinks": true.Json, "folder_exclude_patterns": [".dub"].map!Json.array.Json, ].Json; } Json buildSystems(BuildPlatform buildPlatform, string workingDiretory = getcwd()) { enum BUILD_TYPES = [ //"plain", "debug", "release", "release-nobounds", //"unittest", "docs", "ddox", "profile", "cov", "unittest-cov", ]; auto arch = buildPlatform.architecture[0]; Json makeBuildSystem(string buildType) { return Json([ "name": "DUB build " ~ buildType.Json, "cmd": ["dub", "build", "--build=" ~ buildType, "--arch=" ~ arch].map!Json.array.Json, "file_regex": r"^(.+)\(([0-9]+)\)\:() (.*)$".Json, "working_dir": workingDiretory.Json, "variants": [ [ "name": "Run".Json, "cmd": ["dub", "run", "--build=" ~ buildType, "--arch=" ~ arch].map!Json.array.Json, ].Json ].array.Json, ]); } auto buildSystems = BUILD_TYPES.map!makeBuildSystem.array; buildSystems ~= [ "name": "DUB test".Json, "cmd": ["dub", "test", "--arch=" ~ arch].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-0.9.24/source/dub/generators/targetdescription.d000066400000000000000000000034351267257315000225170ustar00rootroot00000000000000/** 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) { 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 = (Path(ltbs.targetPath) ~ 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-0.9.24/source/dub/generators/visuald.d000066400000000000000000000472311267257315000204360ustar00rootroot00000000000000/** 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.dependencies.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]; auto projectUuid = guid(mainpack); 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) { int i = 0; 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(Path file_path, Path 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 = Path(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.packageInfoFilename.empty) addFile(p.packageInfoFilename.toNativeString(), false); if (files.targetType == TargetType.staticLibrary) foreach(s; files.sourceFiles.filter!(s => !isLinkerFile(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)); Path lastFolder; foreach(source; sortedSources(sourceFiles.values)) { logDebug("source looking at %s", source.structurePath); auto cur = source.structurePath[0 .. source.structurePath.length-1]; 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].toString()); 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 = Path(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 ? Path(buildsettings.targetPath) : Path(".dub/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 = Path(f).relativeTo(project_file_dir); size_t nd = 0; foreach (i; 0 .. rpath.length) if (rpath[i] == "..") 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.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.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(" .dub/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"); 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"; } Path projFileName(string pack) const { auto basepath = Path(".");//Path(".dub/"); version(DUBBING) return basepath ~ (getPackageFileName(pack) ~ ".dubbed.visualdproj"); else return basepath ~ (getPackageFileName(pack) ~ ".visualdproj"); } } // TODO: nice folders struct SourceFile { Path structurePath; Path filePath; bool build; hash_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); auto as = a.structurePath; auto bs = b.structurePath; // 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.head.opCmp(bs.head); } } } auto sortedSources(SourceFile[] sources) { return sort(sources); } unittest { SourceFile[] sfs = [ { Path("b/file.d"), Path("") }, { Path("b/b/fileA.d"), Path("") }, { Path("a/file.d"), Path("") }, { Path("b/b/fileB.d"), Path("") }, { Path("b/b/b/fileA.d"), Path("") }, { Path("b/c/fileA.d"), Path("") }, ]; auto sorted = sort(sfs); SourceFile[] sortedSfs; foreach(sr; sorted) sortedSfs ~= sr; assert(sortedSfs[0].structurePath == Path("a/file.d"), "1"); assert(sortedSfs[1].structurePath == Path("b/b/b/fileA.d"), "2"); assert(sortedSfs[2].structurePath == Path("b/b/fileA.d"), "3"); assert(sortedSfs[3].structurePath == Path("b/b/fileB.d"), "4"); assert(sortedSfs[4].structurePath == Path("b/c/fileA.d"), "5"); assert(sortedSfs[5].structurePath == Path("b/file.d"), "6"); } } private Path determineStructurePath(Path file_path, in ProjectGenerator.TargetInfo target) { foreach (p; target.packages) { if (file_path.startsWith(p.path)) return Path(getPackageFileName(p.name)) ~ file_path[p.path.length .. $]; } return Path("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": return "Win32"; case "x86_64": return "x64"; } } dub-0.9.24/source/dub/init.d000066400000000000000000000127441267257315000155620ustar00rootroot00000000000000/** Empty package initialization code. Copyright: © 2013-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.init; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.package_ : PackageFormat, packageInfoFiles, defaultPackageFilename; import std.datetime; import std.exception; import std.file; import std.format; import std.process; import std.string; void initPackage(Path root_path, string[string] deps, string type, PackageFormat format) { void enforceDoesNotExist(string filename) { enforce(!existsFile(root_path ~ filename), "The target directory already contains a '"~filename~"' file. Aborting."); } //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", ".gitignore"]; foreach (fil; files) enforceDoesNotExist(fil); switch (type) { default: throw new Exception("Unknown package init type: "~type); case "minimal": initMinimalPackage(root_path, deps, format); break; case "vibe.d": initVibeDPackage(root_path, deps, format); break; case "deimos": initDeimosPackage(root_path, deps, format); break; } writeGitignore(root_path); } void initMinimalPackage(Path root_path, string[string] deps, PackageFormat format) { writePackageDescription(format, root_path, "A minimal D application.", deps); 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."); } }); } void initVibeDPackage(Path root_path, string[string] deps, PackageFormat format) { if("vibe-d" !in deps) deps["vibe-d"] = "~>0.7.23"; writePackageDescription(format, root_path, "A simple vibe.d server application.", deps, ["versions": ["VibeDefaultMain"]]); createDirectory(root_path ~ "source"); createDirectory(root_path ~ "views"); createDirectory(root_path ~ "public"); write((root_path ~ "source/app.d").toNativeString(), q{import vibe.d; shared static this() { 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."); } void hello(HTTPServerRequest req, HTTPServerResponse res) { res.writeBody("Hello, World!"); } }); } void initDeimosPackage(Path root_path, string[string] deps, PackageFormat format) { auto name = root_path.head.toString().toLower(); writePackageDescription(format, root_path, "Deimos Bindings for "~name~".", deps, ["importPaths": ["."]], ["targetType": "sourceLibrary"]); createDirectory(root_path ~ "C"); createDirectory(root_path ~ "deimos"); } void writePackageDescription(PackageFormat format, Path root_path, string description, string[string] dependencies = null, string[][string] array_fields = null, string[string] string_fields = null) { final switch (format) { case PackageFormat.json: foreach (f, v; array_fields) string_fields[f] = .format("[%(%s, %)]", v); writePackageJSON(root_path, description, dependencies, string_fields); break; case PackageFormat.sdl: foreach (f, v; array_fields) string_fields[f] = .format("%(%s %)", v); writePackageSDL(root_path, description, dependencies, string_fields); break; } } private void writePackageJSON(Path root_path, string description, string[string] dependencies = null, string[string] raw_fields = null) { import std.algorithm : map; assert(!root_path.empty); string username; version (Windows) username = environment.get("USERNAME", "Peter Parker"); else username = environment.get("USER", "Peter Parker"); auto fil = openFile(root_path ~ "dub.json", FileMode.append); scope(exit) fil.close(); fil.formattedWrite("{\n\t\"name\": \"%s\",\n", root_path.head.toString().toLower()); fil.formattedWrite("\t\"description\": \"%s\",\n", description); fil.formattedWrite("\t\"copyright\": \"Copyright © %s, %s\",\n", Clock.currTime().year, username); fil.formattedWrite("\t\"authors\": [\"%s\"],\n", username); fil.formattedWrite("\t\"dependencies\": {"); fil.formattedWrite("%(\n\t\t%s: %s,%)", dependencies); fil.formattedWrite("\n\t}"); fil.formattedWrite("%-(,\n\t\"%s\": %s%)", raw_fields); fil.write("\n}\n"); } private void writePackageSDL(Path root_path, string description, string[string] dependencies = null, string[string] raw_fields = null) { import std.algorithm : map; assert(!root_path.empty); string username; version (Windows) username = environment.get("USERNAME", "Peter Parker"); else username = environment.get("USER", "Peter Parker"); auto fil = openFile(root_path ~ "dub.sdl", FileMode.append); scope(exit) fil.close(); fil.formattedWrite("name \"%s\"\n", root_path.head.toString().toLower()); fil.formattedWrite("description \"%s\"\n", description); fil.formattedWrite("copyright \"Copyright © %s, %s\"\n", Clock.currTime().year, username); fil.formattedWrite("authors \"%s\"\n", username); foreach (d, v; dependencies) fil.formattedWrite("dependency \"%s\" version=\"%s\"\n", d, v); foreach (f, v; raw_fields) fil.formattedWrite("%s %s\n", f, v); } void writeGitignore(Path root_path) { write((root_path ~ ".gitignore").toNativeString(), ".dub\ndocs.json\n__dummy.html\n*.o\n*.obj\n"); } dub-0.9.24/source/dub/internal/000077500000000000000000000000001267257315000162565ustar00rootroot00000000000000dub-0.9.24/source/dub/internal/libInputVisitor.d000066400000000000000000000035511267257315000215750ustar00rootroot00000000000000module 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-0.9.24/source/dub/internal/sdlang/000077500000000000000000000000001267257315000175265ustar00rootroot00000000000000dub-0.9.24/source/dub/internal/sdlang/ast.d000066400000000000000000001473521267257315000204760ustar00rootroot00000000000000// 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-existant 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-0.9.24/source/dub/internal/sdlang/exception.d000066400000000000000000000013641267257315000216750ustar00rootroot00000000000000// 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-0.9.24/source/dub/internal/sdlang/lexer.d000066400000000000000000001733321267257315000210230ustar00rootroot00000000000000// 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.stream : ByteOrderMarks, BOM; 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 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. /// Returns false if EOF was reached 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] ); } do { advanceChar(ErrorOnEOF.Yes); 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."); } while(ch != '"'); 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; } FracSec fracSecs; fracSecs.msecs = millisecond; 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.fracSec, timezoneStr)")); } else { auto timezone = new immutable SimpleTimeZone(offset.get()); mixin(accept!("Value", "SysTime(dateTimeFrac.dateTime, dateTimeFrac.fracSec, timezone)")); } } try { auto timezone = TimeZone.getTimeZone(timezoneStr); if(timezone) mixin(accept!("Value", "SysTime(dateTimeFrac.dateTime, dateTimeFrac.fracSec, 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.fracSec, 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; } else if(ch == '/' || ch == '-') { commentStart = location; if(lookahead(ch)) { if(!allowComments) return; advanceChar(ErrorOnEOF.No); state = State.lineComment; } else if(ch == '/' && lookahead('*')) { if(!allowComments) return; advanceChar(ErrorOnEOF.No); state = State.blockComment; } 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(isNewline(ch)) 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" )) ]); 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), FracSec.from!"msecs"(123)))) ]); testLex( "2013/2/22 07:53:34.12", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 34), FracSec.from!"msecs"(120)))) ]); testLex( "2013/2/22 07:53:34.1", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 34), FracSec.from!"msecs"(100)))) ]); testLex( "2013/2/22 07:53.123", [ Token(symbol!"Value",loc,Value(DateTimeFrac(DateTime( 2013, 2, 22, 7, 53, 0), FracSec.from!"msecs"(123)))) ]); 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), FracSec.from!"msecs"(123)))) ]); 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), FracSec.from!"msecs"(123)))) ]); 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), FracSec.from!"msecs"(-123)))) ]); 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), FracSec.from!"msecs"(-123)))) ]); 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), FracSec.from!"msecs"(123), 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), FracSec.from!"msecs"(123), 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), FracSec.from!"msecs"(123), 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), FracSec.from!"msecs"(123), 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), FracSec.from!"msecs"(123), 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), FracSec.from!"msecs"(123), 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 = FracSec.from!"msecs"(0); 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), FracSec.from!"msecs"( 0), "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), FracSec.from!"msecs"( 0), "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), FracSec.from!"msecs"( 0), "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), FracSec.from!"msecs"( 0), "Bogus/Foo"))) ]); testLex( "2013/2/22 07:53:34-Bogus/Foo", [ Token(symbol!"Value",loc,Value(DateTimeFracUnknownZone(DateTime( 2013, 2, 22, 7, 53, 34), FracSec.from!"msecs"( 0), "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), FracSec.from!"msecs"(123), "Bogus/Foo"))) ]); testLex( "2013/2/22 07:53.123-Bogus/Foo", [ Token(symbol!"Value",loc,Value(DateTimeFracUnknownZone(DateTime( 2013, 2, 22, 7, 53, 0), FracSec.from!"msecs"(123), "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!"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!"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(); testLex("//X\na", [ Token(symbol!"Ident",loc,Value(null),"a") ]); testLex("//\na", [ Token(symbol!"Ident",loc,Value(null),"a") ]); testLex("--\na", [ Token(symbol!"Ident",loc,Value(null),"a") ]); testLex("#\na", [ Token(symbol!"Ident",loc,Value(null),"a") ]); } 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-0.9.24/source/dub/internal/sdlang/package.d000066400000000000000000000052621267257315000212730ustar00rootroot00000000000000// SDLang-D // Written in the D programming language. /++ SDLang-D: Library for parsing SDL (Simple Declarative Language). Import this module to use SDLang-D as a library. This should work with DMD 2.061 and up (currently tested up through v2.067.0). Homepage: http://github.com/Abscissa/SDLang-D API: http://semitwist.com/sdlang-d-api SDL: http://sdl.ikayzo.org/display/SDL/Language+Guide Authors: Nick Sabalausky ("Abscissa") http://semitwist.com/contact +/ 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-0.9.24/source/dub/internal/sdlang/parser.d000066400000000000000000000312701267257315000211720ustar00rootroot00000000000000// 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 $(WEB 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(); } } dub-0.9.24/source/dub/internal/sdlang/symbol.d000066400000000000000000000021711267257315000212010ustar00rootroot00000000000000// 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-0.9.24/source/dub/internal/sdlang/token.d000066400000000000000000000401721267257315000210170ustar00rootroot00000000000000// 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 { DateTime dateTime; FracSec fracSec; } /++ 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; FracSec fracSec; string timeZone; bool opEquals(const DateTimeFracUnknownZone b) const { return opEquals(b); } bool opEquals(ref const DateTimeFracUnknownZone b) const { return this.dateTime == b.dateTime && this.fracSec == b.fracSec && 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.fracSec.msecs != 0) { sink.put('.'); sink.put("%.3s".format(value.fracSec.msecs)); } } void toSDLString(Sink)(SysTime value, ref Sink sink) if(isOutputRange!(Sink,char)) { auto dateTimeFrac = DateTimeFrac(cast(DateTime)value, value.fracSec); 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("+"); sink.put("%.2s".format(offset.hours)); sink.put(":"); sink.put("%.2s".format(offset.minutes)); } else sink.put(tzString); } void toSDLString(Sink)(DateTimeFracUnknownZone value, ref Sink sink) if(isOutputRange!(Sink,char)) { auto dateTimeFrac = DateTimeFrac(value.dateTime, value.fracSec); 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:"); } sink.put("%.2s".format(value.hours)); sink.put(':'); sink.put("%.2s".format(value.minutes)); sink.put(':'); sink.put("%.2s".format(value.seconds)); if(value.fracSec.msecs != 0) { sink.put('.'); sink.put("%.3s".format(value.fracSec.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), FracSec.from!"msecs"(123))).toSDLString() == "2004/10/31 14:30:15.123"); assert(Value(DateTimeFrac(DateTime(2004,10,31, 14,30,15), FracSec.from!"msecs"(120))).toSDLString() == "2004/10/31 14:30:15.120"); assert(Value(DateTimeFrac(DateTime(2004,10,31, 14,30,15), FracSec.from!"msecs"(100))).toSDLString() == "2004/10/31 14:30:15.100"); assert(Value(DateTimeFrac(DateTime(2004,10,31, 14,30,15), FracSec.from!"msecs"( 12))).toSDLString() == "2004/10/31 14:30:15.012"); assert(Value(DateTimeFrac(DateTime(2004,10,31, 14,30,15), FracSec.from!"msecs"( 1))).toSDLString() == "2004/10/31 14:30:15.001"); assert(Value(DateTimeFrac(DateTime(-2004,10,31, 14,30,15), FracSec.from!"msecs"(123))).toSDLString() == "-2004/10/31 14:30:15.123"); // DateTimeFracUnknownZone assert(Value(DateTimeFracUnknownZone(DateTime(2004,10,31, 14,30,15), FracSec.from!"msecs"(123), "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), FracSec.from!"msecs"(123), 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-0.9.24/source/dub/internal/sdlang/util.d000066400000000000000000000042241267257315000206520ustar00rootroot00000000000000// 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}"; } dub-0.9.24/source/dub/internal/utils.d000066400000000000000000000177331267257315000175760ustar00rootroot00000000000000/** ... 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.version_; // todo: cleanup imports. import std.algorithm : startsWith; import std.array; import std.conv; import std.exception; import std.file; import std.process; import std.string; import std.traits : isIntegral; import std.typecons; import std.zip; version(DubUseCurl) import std.net.curl; Path getTempDir() { return Path(std.file.tempDir()); } private Path[] temporary_files; Path getTempFile(string prefix, string extension = null) { import std.uuid : randomUUID; auto path = getTempDir() ~ (prefix ~ "-" ~ randomUUID.toString() ~ extension); temporary_files ~= path; return path; } static ~this() { foreach (path; temporary_files) { std.file.remove(path.toNativeString()); } } bool isEmptyDir(Path p) { foreach(DirEntry e; dirEntries(p.toNativeString(), SpanMode.shallow)) return false; return true; } bool isWritableDir(Path 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(Path 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()); } Json jsonFromZip(Path zip, string filename) { 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); auto text = stripUTF8Bom(cast(string)archive.expand(archive.directory[filename])); return parseJsonString(text, zip.toNativeString~"/"~filename); } void writeJsonFile(Path path, Json json) { auto f = openFile(path, FileMode.createTrunc); scope(exit) f.close(); f.writePrettyJsonString(json); } bool isPathFromZip(string p) { enforce(p.length > 0); return p[$-1] == '/'; } bool existsDirectory(Path path) { if( !existsFile(path) ) return false; auto fi = getFileInfo(path); return fi.isDirectory; } void runCommands(in string[] commands, string[string] env = 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); auto exitcode = pid.wait(); enforce(exitcode == 0, "Command failed with exit code "~to!string(exitcode)); } } /** 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. */ void download(string url, string filename) { version(DubUseCurl) { auto conn = HTTP(); setupHTTPClient(conn); logDebug("Storing %s...", url); std.net.curl.download(url, filename, conn); enforce(conn.statusLine.code < 400, format("Failed to download %s: %s %s", url, conn.statusLine.code, conn.statusLine.reason)); } else version (Have_vibe_d) { import vibe.inet.urltransfer; vibe.inet.urltransfer.download(url, filename); } else assert(false); } /// ditto void download(URL url, Path filename) { download(url.toString(), filename.toNativeString()); } /// ditto ubyte[] download(string url) { version(DubUseCurl) { auto conn = HTTP(); setupHTTPClient(conn); logDebug("Getting %s...", url); auto ret = cast(ubyte[])get(url, conn); enforce(conn.statusLine.code < 400, format("Failed to GET %s: %s %s", url, conn.statusLine.code, conn.statusLine.reason)); return ret; } else version (Have_vibe_d) { import vibe.inet.urltransfer; import vibe.stream.operations; ubyte[] ret; download(url, (scope input) { ret = input.readAll(); }); return ret; } else assert(false); } /// ditto ubyte[] download(URL url) { return download(url.toString()); } /// Returns the current DUB version in semantic version format string getDUBVersion() { import dub.version_; // 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; } version(DubUseCurl) { void setupHTTPClient(ref HTTP conn) { static if( is(typeof(&conn.verifyPeer)) ) conn.verifyPeer = false; auto proxy = environment.get("http_proxy", null); if (proxy.length) conn.proxy = proxy; 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)); } dub-0.9.24/source/dub/internal/vibecompat/000077500000000000000000000000001267257315000204075ustar00rootroot00000000000000dub-0.9.24/source/dub/internal/vibecompat/core/000077500000000000000000000000001267257315000213375ustar00rootroot00000000000000dub-0.9.24/source/dub/internal/vibecompat/core/file.d000066400000000000000000000173371267257315000224360ustar00rootroot00000000000000/** 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; static import std.stream; import std.string; import std.utf; /* Add output range support to File */ struct RangeFile { std.stream.File file; void put(in ubyte[] bytes) { file.writeExact(bytes.ptr, bytes.length); } void put(in char[] str) { put(cast(ubyte[])str); } void put(char ch) { put((&ch)[0 .. 1]); } void put(dchar ch) { char[4] chars; put(chars[0 .. encode(chars, ch)]); } ubyte[] readAll() { file.seek(0, std.stream.SeekPos.End); auto sz = file.position; enforce(sz <= size_t.max, "File is too big to read to memory."); file.seek(0, std.stream.SeekPos.Set); auto ret = new ubyte[cast(size_t)sz]; file.readExact(ret.ptr, ret.length); return ret; } void rawRead(ubyte[] dst) { file.readExact(dst.ptr, dst.length); } void write(string str) { put(str); } void close() { file.close(); } void flush() { file.flush(); } @property ulong size() { return file.size; } } /** Opens a file stream with the specified mode. */ RangeFile openFile(Path path, FileMode mode = FileMode.read) { std.stream.FileMode fmode; final switch(mode){ case FileMode.read: fmode = std.stream.FileMode.In; break; case FileMode.readWrite: fmode = std.stream.FileMode.Out; break; case FileMode.createTrunc: fmode = std.stream.FileMode.OutNew; break; case FileMode.append: fmode = std.stream.FileMode.Append; break; } auto ret = new std.stream.File(path.toNativeString(), fmode); assert(ret.isOpen); return RangeFile(ret); } /// ditto RangeFile openFile(string path, FileMode mode = FileMode.read) { return openFile(Path(path), mode); } /** Moves or renames a file. */ void moveFile(Path from, Path 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 = Path of the source file to = Path 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(Path from, Path 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); } .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(Path(from), Path(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(Path a, Path b) { static assert(__traits(allMembers, FileInfo)[0] == "name"); return getFileInfo(a).tupleof[1 .. $] == getFileInfo(b).tupleof[1 .. $]; } /** Creates a hardlink. */ void hardLinkFile(Path from, Path to, bool overwrite = false) { if (existsFile(to)) { enforce(overwrite, "Destination file already exists."); if (auto fe = collectException!FileException(removeFile(to))) { version (Windows) 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(Path path) { removeFile(path.toNativeString()); } /// ditto void removeFile(string path) { std.file.remove(path); } /** Checks if a file exists */ bool existsFile(Path 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(Path path) { static if (__VERSION__ >= 2064) auto ent = std.file.DirEntry(path.toNativeString()); else auto ent = std.file.dirEntry(path.toNativeString()); return makeFileInfo(ent); } /// ditto FileInfo getFileInfo(string path) { return getFileInfo(Path(path)); } /** Creates a new directory. */ void createDirectory(Path path) { mkdir(path.toNativeString()); } /// ditto void createDirectory(string path) { createDirectory(Path(path)); } /** Enumerates all files in the specified directory. */ void listDirectory(Path 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(Path(path), del); } /// ditto int delegate(scope int delegate(ref FileInfo)) iterateDirectory(Path 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(Path(path)); } /** Returns the current working directory. */ Path getWorkingDirectory() { return Path(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-0.9.24/source/dub/internal/vibecompat/core/log.d000066400000000000000000000045141267257315000222710ustar00rootroot00000000000000/** 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 = cast(ulong)cast(void*)Thread.getThis(); auto fiberid = cast(ulong)cast(void*)Fiber.getThis(); threadid ^= threadid >> 32; fiberid ^= fiberid >> 32; if( level >= s_minLevel ){ if (level == LogLevel.info) { stdout.writeln(txt.data); stdout.flush(); } else { stderr.writeln(txt.data); stderr.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-0.9.24/source/dub/internal/vibecompat/data/000077500000000000000000000000001267257315000213205ustar00rootroot00000000000000dub-0.9.24/source/dub/internal/vibecompat/data/json.d000066400000000000000000001773621267257315000224560ustar00rootroot00000000000000/** 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) 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.string; import std.range; 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) { 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 teh $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; } /** Scheduled for deprecation, please use `opIndex` instead. Allows to access existing fields of a JSON object using dot syntax. */ @property const(Json) opDispatch(string prop)() const { return opIndex(prop); } /// ditto @property ref Json opDispatch(string prop)() { return opIndex(prop); } /** 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 occured. */ Json parseJson(R)(ref R range, int* line = null, string filename = null) if( is(R == string) ) { 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); if( is_float ) ret = to!double(num); else ret = to!long(num); break; case '\"': ret = skipJsonString(range); 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); 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) { 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 { 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(&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); 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(&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; foreach( string k, ref const Json e; json ){ if( e.type == Json.Type.undefined ) continue; if( !first ) dst.put(','); first = false; static if (pretty) { dst.put('\n'); foreach (tab; 0 .. level+1) dst.put('\t'); } dst.put('\"'); jsonEscape(dst, k); dst.put(pretty ? `": ` : `":`); 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; } } 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, {} ] }` || a.toPrettyString() == `{ "b": [ 1, {} ], "a": [] }`); } 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 std.c.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) { 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."); switch(range.front){ default: enforceJson(false, "Invalid string escape sequence."); 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'."); 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'."); } 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"); { /* 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) { // 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."); 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]); 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, int* line = null) { // TODO: count or disallow any newlines inside of the string enforceJson(!s.empty && s.front == '"', "Expected '\"' to start string."); s.popFront(); string ret = jsonUnescape(s); enforceJson(!s.empty && s.front == '"', "Expected '\"' to terminate string."); 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__ >= 2065) enforceEx!JSONException(cond, message, file, line); else if (!cond) throw new JSONException(message); } 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__ >= 2065) enforceEx!JSONException(cond, errmsg, file, line); else if (!cond) throw new JSONException(errmsg); } 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-0.9.24/source/dub/internal/vibecompat/data/serialization.d000066400000000000000000001235341267257315000243520ustar00rootroot00000000000000/** 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) 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); } } } /// static if (__VERSION__ >= 2065) 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); } /// static if (__VERSION__ >= 2065) 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; static if (__VERSION__ >= 2067) 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 (__VERSION__ >= 2067 && 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; static if (__VERSION__ >= 2067) 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 (__VERSION__ >= 2067 && 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)"); test(["hello": "world"], "D(HAyaAya){DE(Aya,hello)(V(Aya)(world))DE(Aya,hello)}D(HAyaAya)"); 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); } static if (__VERSION__ >= 2067) 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-0.9.24/source/dub/internal/vibecompat/data/utils.d000066400000000000000000000465141267257315000226370ustar00rootroot00000000000000/** 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) {} 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; } } enum plainFields = ["i"]; enum 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]); } } /** Compares two groups for element identity Params: Group1, Group2 = any instances of `Group` Returns: `true` if each element of Group1 is identical to the one of Group2 at the same index */ template Compare(alias Group1, alias Group2) if (isGroup!Group1 && isGroup!Group2) { private bool implementation() { static if (Group1.expand.length == Group2.expand.length) { foreach (index, element; Group1.expand) { static if (!isSame!(Group1.expand[index], Group2.expand[index])) { return false; } } return true; } else { return false; } } enum Compare = implementation(); } /// unittest { alias one = Group!(int, double); alias two = Group!(int, double); alias three = Group!(double, int); static assert (Compare!(one, two)); static assert (!Compare!(one, three)); } /** 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-0.9.24/source/dub/internal/vibecompat/inet/000077500000000000000000000000001267257315000213465ustar00rootroot00000000000000dub-0.9.24/source/dub/internal/vibecompat/inet/path.d000066400000000000000000000355661267257315000224660ustar00rootroot00000000000000/** 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_d) public import vibe.inet.path; else: import std.algorithm; import std.array; import std.conv; import std.exception; import std.string; /** 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 Path { private { immutable(PathEntry)[] m_nodes; bool m_absolute = false; bool m_endsWithSlash = false; } /// Constructs a Path object by parsing a path string. this(string pathstr) { static if (__VERSION__ < 2066) m_nodes = splitPath(pathstr).idup; else 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 Path 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 Path 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. Path relativeTo(const Path parentPath) const { assert(this.absolute && parentPath.absolute); 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); Path ret = Path(null, false); assert(m_nodes.length >= parentPath.length - nup); ret.m_endsWithSlash = true; foreach( i; 0 .. nup ) ret ~= ".."; ret ~= Path(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); return m_nodes[$-1]; } /// The parent path @property Path 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]; } Path opSlice(size_t start, size_t end) const { auto ret = Path(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; } Path opBinary(string OP)(const Path rhs) const if( OP == "~" ) { Path 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."); size_t idx = m_nodes.length; 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; } Path opBinary(string OP)(string rhs) const if( OP == "~" ) { assert(rhs.length > 0, "Cannot append empty path string."); return opBinary!"~"(Path(rhs)); } Path opBinary(string OP)(PathEntry rhs) const if( OP == "~" ) { assert(rhs.toString().length > 0, "Cannot append empty path string."); return opBinary!"~"(Path(rhs)); } void opOpAssign(string OP)(string rhs) if( OP == "~" ) { assert(rhs.length > 0, "Cannot append empty path string."); opOpAssign!"~"(Path(rhs)); } void opOpAssign(string OP)(PathEntry rhs) if( OP == "~" ) { assert(rhs.toString().length > 0, "Cannot append empty path string."); opOpAssign!"~"(Path(rhs)); } void opOpAssign(string OP)(Path 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 Path 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 Path other) const { return opEquals(other); } int opCmp(ref const Path 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; } hash_t toHash() const nothrow @trusted { hash_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; } Path opBinary(string OP)(PathEntry rhs) const if( OP == "~" ) { return Path([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) { Path p1 = Path(basepath); Path p2 = Path(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 { Path p; assert(p.toNativeString() == "."); p.endsWithSlash = true; version(Windows) assert(p.toNativeString() == ".\\"); else assert(p.toNativeString() == "./"); p = Path("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 = Path(unc); uncp.normalize(); version(Windows) assert(uncp.toNativeString() == unc); assert(uncp.absolute); assert(!uncp.endsWithSlash); } { auto abspath = "/test/path/"; auto abspathp = Path(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 = Path(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 = Path(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 = Path(dotpath); assert(dotpathp.toString() == "/test/../test2/././x/y"); dotpathp.normalize(); assert(dotpathp.toString() == "/test2/x/y"); } { auto dotpath = "/test/..////test2//./x/y"; auto dotpathp = Path(dotpath); assert(dotpathp.toString() == "/test/..////test2//./x/y"); dotpathp.normalize(); assert(dotpathp.toString() == "/test2/x/y"); } { auto parentpath = "/path/to/parent"; auto parentpathp = Path(parentpath); auto subpath = "/path/to/parent/sub/"; auto subpathp = Path(subpath); auto subpath_rel = "sub/"; assert(subpathp.relativeTo(parentpathp).toString() == subpath_rel); auto subfile = "/path/to/parent/child"; auto subfilep = Path(subfile); auto subfile_rel = "child"; assert(subfilep.relativeTo(parentpathp).toString() == subfile_rel); } { // relative paths across Windows devices are not allowed version (Windows) { auto p1 = Path("\\\\server\\share"); assert(p1.absolute); auto p2 = Path("\\\\server\\othershare"); assert(p2.absolute); auto p3 = Path("\\\\otherserver\\share"); assert(p3.absolute); auto p4 = Path("C:\\somepath"); assert(p4.absolute); auto p5 = Path("C:\\someotherpath"); assert(p5.absolute); auto p6 = Path("D:\\somepath"); assert(p6.absolute); assert(p4.relativeTo(p5) == Path("../somepath")); assert(p4.relativeTo(p6) == Path("C:\\somepath")); assert(p4.relativeTo(p1) == Path("C:\\somepath")); assert(p1.relativeTo(p2) == Path("../share")); assert(p1.relativeTo(p3) == Path("\\\\server\\share")); assert(p1.relativeTo(p4) == Path("\\\\server\\share")); } } } unittest { assert(Path("/foo/bar/baz").relativeTo(Path("/foo")).toString == "bar/baz"); assert(Path("/foo/bar/baz/").relativeTo(Path("/foo")).toString == "bar/baz/"); assert(Path("/foo/bar").relativeTo(Path("/foo")).toString == "bar"); assert(Path("/foo/bar/").relativeTo(Path("/foo")).toString == "bar/"); assert(Path("/foo").relativeTo(Path("/foo/bar")).toString() == ".."); assert(Path("/foo/").relativeTo(Path("/foo/bar")).toString() == "../"); assert(Path("/foo/baz").relativeTo(Path("/foo/bar/baz")).toString() == "../../baz"); assert(Path("/foo/baz/").relativeTo(Path("/foo/bar/baz")).toString() == "../../baz/"); assert(Path("/foo/").relativeTo(Path("/foo/bar/baz")).toString() == "../../"); assert(Path("/foo/").relativeTo(Path("/foo/bar/baz/mumpitz")).toString() == "../../../"); assert(Path("/foo").relativeTo(Path("/foo")).toString() == ""); assert(Path("/foo/").relativeTo(Path("/foo")).toString() == ""); } dub-0.9.24/source/dub/internal/vibecompat/inet/url.d000066400000000000000000000164431267257315000223250ustar00rootroot00000000000000/** 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) public import vibe.inet.url; else: import std.algorithm; import std.array; import std.conv; import std.exception; import std.string; import std.uri; /** Represents a URL decomposed into its components. */ struct URL { private { string m_schema; string m_pathString; Path m_path; string m_host; ushort m_port; string m_username; string m_password; string m_queryString; string m_anchor; } /// Constructs a new URL object from its components. this(string schema, string host, ushort port, Path path) { m_schema = schema; m_host = host; m_port = port; m_path = path; m_pathString = path.toString(); } /// ditto this(string schema, Path 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; switch(m_schema){ case "http": case "https": case "ftp": case "spdy": case "sftp": case "file": // proto://server/path style enforce(str.startsWith("//"), "URL must start with proto://..."); requires_host = true; str = str[2 .. $]; goto default; default: auto si = str.countUntil('/'); if( si < 0 ) si = str.length; auto ai = str[0 .. si].countUntil('@'); sizediff_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; } /// 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 Path path() const { return m_path; } /// ditto @property void path(Path 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 = Path(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(":"); switch(schema){ default: break; case "file": case "http": case "https": case "ftp": case "spdy": case "sftp": dst.put("//"); break; } 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)(Path 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)(Path 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 == Path("/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); } dub-0.9.24/source/dub/package_.d000066400000000000000000000503201267257315000163410ustar00rootroot00000000000000/** Stuff with dependencies. Copyright: © 2012-2013 Matthias Dondorff, © 2012-2015 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.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; enum PackageFormat { json, sdl } struct FilenameAndFormat { string filename; PackageFormat format; } struct PathAndFormat { Path path; PackageFormat format; @property bool empty() { return path.empty; } string toString() const { return path.toString(); } } // Supported package descriptions in decreasing order of preference. static immutable FilenameAndFormat[] packageInfoFiles = [ {"dub.json", PackageFormat.json}, {"dub.sdl", PackageFormat.sdl}, {"package.json", PackageFormat.json} ]; @property string[] packageInfoFilenames() { return packageInfoFiles.map!(f => cast(string)f.filename).array; } @property string defaultPackageFilename() { return packageInfoFiles[0].filename; } /** Represents a package, including its sub packages Documentation of the dub.json can be found at http://registry.vibed.org/package-format */ class Package { private { Path m_path; PathAndFormat m_infoFile; PackageRecipe m_info; Package m_parentPackage; } static PathAndFormat findPackageFile(Path path) { foreach(file; packageInfoFiles) { auto filename = path ~ file.filename; if(existsFile(filename)) return PathAndFormat(filename, file.format); } return PathAndFormat(Path()); } this(Path root, PathAndFormat infoFile = PathAndFormat(), Package parent = null, string versionOverride = "") { RawPackage raw_package; m_infoFile = infoFile; try { if(m_infoFile.empty) { m_infoFile = findPackageFile(root); if(m_infoFile.empty) throw new Exception( "No package file found in %s, expected one of %s" .format(root.toNativeString(), packageInfoFiles.map!(f => cast(string)f.filename).join("/"))); } raw_package = rawPackageFromFile(m_infoFile); } catch (Exception ex) throw ex;//throw new Exception(format("Failed to load package %s: %s", m_infoFile.toNativeString(), ex.msg)); enforce(raw_package !is null, format("Missing package description for package at %s", root.toNativeString())); this(raw_package, root, parent, versionOverride); } this(Json package_info, Path root = Path(), Package parent = null, string versionOverride = "") { this(new JsonPackage(package_info), root, parent, versionOverride); } this(RawPackage raw_package, Path root = Path(), Package parent = null, string versionOverride = "") { PackageRecipe recipe; // parse the Package description if(raw_package !is null) { scope(failure) logError("Failed to parse package description for %s %s in %s.", raw_package.package_name, versionOverride.length ? versionOverride : raw_package.version_, root.length ? root.toNativeString() : "remote location"); raw_package.parseInto(recipe, parent ? parent.name : null); if (!versionOverride.empty) recipe.version_ = versionOverride; // 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.MASTER.toString(); } else logDiagnostic("Determined package version using GIT: %s %s", recipe.name, recipe.version_); } } this(recipe, root, parent); } this(PackageRecipe recipe, Path root = Path(), Package parent = null) { m_parentPackage = parent; m_path = root; m_path.endsWithSlash = true; // use the given recipe as the basis m_info = recipe; fillWithDefaults(); simpleLint(); } @property string name() const { if (m_parentPackage) return m_parentPackage.name ~ ":" ~ m_info.name; else return m_info.name; } @property string vers() const { return m_parentPackage ? m_parentPackage.vers : m_info.version_; } @property Version ver() const { return Version(this.vers); } @property void ver(Version ver) { assert(m_parentPackage is null); m_info.version_ = ver.toString(); } @property ref inout(PackageRecipe) info() inout { return m_info; } @property Path path() const { return m_path; } @property Path packageInfoFilename() const { return m_infoFile.path; } @property const(Dependency[string]) dependencies() const { return m_info.dependencies; } @property inout(Package) basePackage() inout { return m_parentPackage ? m_parentPackage.basePackage : this; } @property inout(Package) parentPackage() inout { return m_parentPackage; } @property inout(SubPackage)[] subPackages() inout { return m_info.subPackages; } @property string[] configurations() const { auto ret = appender!(string[])(); foreach( ref config; m_info.configurations ) ret.put(config.name); return ret.data; } 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; } /** Overwrites the packge description file using the default filename with the current information. */ void storeInfo() { storeInfo(m_path); m_infoFile = PathAndFormat(m_path ~ defaultPackageFilename); } /// ditto void storeInfo(Path path) const { enforce(!ver.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()); } 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(); } 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); } 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 config. 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 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; } 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-nobounds": settings.addOptions(releaseMode, optimize, inline, noBoundsCheck); break; case "unittest": settings.addOptions(unittests, debugMode, debugInfo); break; case "docs": settings.addOptions(syntaxOnly); settings.addDFlags("-c", "-Dddocs"); break; case "ddox": settings.addOptions(syntaxOnly); settings.addDFlags("-c", "-Df__dummy.html", "-Xfdocs.json"); 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; } } } 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 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 string[] getPlatformConfigurations(in BuildPlatform platform, bool is_main_package = false) const { auto ret = appender!(string[]); foreach(ref conf; m_info.configurations){ if (!conf.matchesPlatform(platform)) continue; if (!is_main_package && conf.buildSettings.targetType == TargetType.executable) continue; ret ~= conf.name; } if (ret.data.length == 0) ret.put(null); return ret.data; } /// Human readable information of this package and its dependencies. string generateInfoString() const { string s; s ~= m_info.name ~ ", version '" ~ m_info.version_ ~ "'"; s ~= "\n Dependencies:"; foreach(string p, ref const Dependency v; m_info.dependencies) s ~= "\n " ~ p ~ ", version '" ~ v.toString() ~ "'"; return s; } bool hasDependency(string depname, string config) const { if (depname in m_info.buildSettings.dependencies) return true; foreach (ref c; m_info.configurations) if ((config.empty || c.name == config) && depname in c.buildSettings.dependencies) return true; return false; } /** Returns a description of the package for use in IDEs or build tools. */ PackageDescription describe(BuildPlatform platform, string config) const { PackageDescription ret; ret.configuration = config; ret.path = m_path.toNativeString(); ret.name = this.name; ret.version_ = this.ver; 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) ret.targetFileName = 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.type = sourceFileTypes[f]; ret.files ~= sf; } return ret; } // ditto deprecated void describe(ref Json dst, BuildPlatform platform, string config) { auto res = describe(platform, config); foreach (string key, value; res.serializeToJson()) dst[key] = value; } 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 = (Path(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); } } } private void simpleLint() const { if (m_parentPackage) { if (m_parentPackage.path != path) { if (info.license.length && info.license != m_parentPackage.info.license) logWarn("License in subpackage %s is different than it's parent package, this is discouraged.", name); } } if (name.empty) logWarn("The package in %s has no name.", path); } private static RawPackage rawPackageFromFile(PathAndFormat file, bool silent_fail = false) { if( silent_fail && !existsFile(file.path) ) return null; string text; { auto f = openFile(file.path.toNativeString(), FileMode.read); scope(exit) f.close(); text = stripUTF8Bom(cast(string)f.readAll()); } final switch(file.format) { case PackageFormat.json: return new JsonPackage(parseJsonString(text, file.path.toNativeString())); case PackageFormat.sdl: return new SdlPackage(text, file.path.toNativeString()); } } static abstract class RawPackage { string package_name; // Should already be lower case string version_; abstract void parseInto(ref PackageRecipe package_, string parent_name); } private static class JsonPackage : RawPackage { Json json; this(Json json) { this.json = json; string nameLower; if(json.type == Json.Type.string) { nameLower = json.get!string.toLower(); this.json = nameLower; } else { nameLower = json.name.get!string.toLower(); this.package_name = nameLower; Json versionJson = json["version"]; this.version_ = (versionJson.type == Json.Type.undefined) ? null : versionJson.get!string; } this.package_name = nameLower; } override void parseInto(ref PackageRecipe recipe, string parent_name) { recipe.parseJson(json, parent_name); } } private static class SdlPackage : RawPackage { import dub.internal.sdlang; Tag sdl; this(string sdl_text, string filename) { this.sdl = parseSource(sdl_text, filename); foreach (t; this.sdl.tags) { switch (t.name) { default: break; case "name": this.package_name = t.values[0].get!string.toLower(); break; case "version": this.version_ = t.values[0].get!string; break; } } } override void parseInto(ref PackageRecipe recipe, string parent_name) { recipe.parseSDL(sdl, parent_name); } } } private string determineVersionFromSCM(Path path) { import std.process; import dub.semver; 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-0.9.24/source/dub/packagemanager.d000066400000000000000000000531571267257315000175500ustar00rootroot00000000000000/** Management of packages on the local computer. Copyright: © 2012-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, 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[LocalPackageType] m_repositories; Path[] m_searchPath; Package[] m_packages; Package[] m_temporaryPackages; bool m_disableDefaultSearchPaths = false; } this(Path user_path, Path system_path, bool refresh_packages = true) { m_repositories[LocalPackageType.user] = Repository(user_path); m_repositories[LocalPackageType.system] = Repository(system_path); if (refresh_packages) refresh(true); } @property void searchPath(Path[] paths) { if (paths == m_searchPath) return; m_searchPath = paths.dup; refresh(false); } @property const(Path)[] searchPath() const { return m_searchPath; } @property void disableDefaultSearchPaths(bool val) { if (val == m_disableDefaultSearchPaths) return; m_disableDefaultSearchPaths = val; refresh(true); } @property const(Path)[] completeSearchPath() const { auto ret = appender!(Path[])(); ret.put(m_searchPath); if (!m_disableDefaultSearchPaths) { ret.put(m_repositories[LocalPackageType.user].searchPath); ret.put(m_repositories[LocalPackageType.user].packagePath); ret.put(m_repositories[LocalPackageType.system].searchPath); ret.put(m_repositories[LocalPackageType.system].packagePath); } return ret.data; } /** 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 (tp; [LocalPackageType.user, LocalPackageType.system]) foreach (ovr; m_repositories[tp].overrides) if (ovr.package_ == name && ovr.version_.matches(ver)) { Package pack; if (!ovr.targetPath.empty) pack = getPackage(name, 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.ver == 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, Path path) { auto ret = getPackage(name, path); if (!ret || ret.ver != ver) return null; return ret; } /// ditto Package getPackage(string name, string ver, Path path) { return getPackage(name, Version(ver), path); } /// ditto Package getPackage(string name, Path 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; } Package getOrLoadPackage(Path path, PathAndFormat infoFile = PathAndFormat(), 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 = new Package(path, infoFile); 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.ver) && (!ret || p.ver > ret.ver)) ret = p; if (enable_overrides && ret) { if (auto ovr = getPackage(name, ret.ver)) return ovr; } return ret; } /// ditto Package getBestPackage(string name, string version_spec) { return getBestPackage(name, Dependency(version_spec)); } 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; foreach (rep; m_repositories) { auto rpath = rep.packagePath; if (ppath.startsWith(rpath)) return true; } return false; } 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 (tp; LocalPackageType.min .. LocalPackageType.max+1) foreach (p; m_repositories[cast(LocalPackageType)tp].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; } 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, Path 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(Path zip_file_path, Json package_info, Path destination) { auto package_name = package_info.name.get!string; auto package_version = package_info["version"].get!string; auto clean_package_version = package_version[package_version.startsWith("~") ? 1 : 0 .. $]; logDiagnostic("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 Path zip_prefix; outer: foreach(ArchiveMember am; archive.directory) { auto path = Path(am.name); foreach (fil; packageInfoFiles) if (path.length == 2 && path.head.toString == fil.filename) { zip_prefix = path[0 .. $-1]; break outer; } } logDebug("zip root folder: %s", zip_prefix); Path getCleanedPath(string fileName) { auto path = Path(fileName); if(zip_prefix != Path() && !path.startsWith(zip_prefix)) return Path(); return path[zip_prefix.length..path.length]; } // extract & place mkdirRecurse(destination.toNativeString()); logDiagnostic("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)); ++countFiles; } } logDiagnostic("%s file(s) copied.", to!string(countFiles)); // overwrite dub.json (this one includes a version field) auto pack = new Package(destination, PathAndFormat(), null, package_info["version"].get!string); if (pack.packageInfoFilename.head != defaultPackageFilename) // Storeinfo saved a default file, this could be different to the file from the zip. removeFile(pack.packageInfoFilename); pack.storeInfo(); addPackages(m_packages, pack); return pack; } /// Removes the given the package. void remove(in Package pack, bool force_remove) { logDebug("Remove %s, version %s, path '%s'", pack.name, pack.vers, 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~"'"); } Package addLocalPackage(Path path, string verName, LocalPackageType type) { path.endsWithSlash = true; auto pack = new Package(path); enforce(pack.name.length, "The package has no name, defined in: " ~ path.toString()); if (verName.length) pack.ver = Version(verName); // don't double-add packages Package[]* packs = &m_repositories[type].localPackages; foreach (p; *packs) { if (p.path == path) { enforce(p.ver == pack.ver, "Adding the same local package twice with differing versions is not allowed."); logInfo("Package is already registered: %s (version: %s)", p.name, p.ver); return p; } } addPackages(*packs, pack); writeLocalPackageList(type); logInfo("Registered package: %s (version: %s)", pack.name, pack.ver); return pack; } void removeLocalPackage(Path 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].ver] = (*packs)[i].name; *packs = (*packs)[0 .. i] ~ (*packs)[i+1 .. $]; } writeLocalPackageList(type); foreach(ver, name; removed) logInfo("Unregistered package: %s (version: %s)", name, ver); } /// For the given type add another path where packages will be looked up. void addSearchPath(Path path, LocalPackageType type) { m_repositories[type].searchPath ~= path; writeLocalPackageList(type); } /// Removes a search path from the given type. void removeSearchPath(Path 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) { Path list_path = m_repositories[type].packagePath; Package[] packs; Path[] 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 = Path(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 = new Package(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.ver = 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); auto old_packages = m_packages; // rescan the system and user package folder void scanPackageFolder(Path 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 (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 = new Package(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 = Path(pv.get!string); m_repositories[type].overrides ~= ovr; } } } 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(Path(file.name).head.toString())) continue; else if(ignored_files.canFind(Path(file.name).head.toString())) continue; sha1.put(cast(ubyte[])Path(file.name).head.toString()); if(file.isDir) { logDebug("Hashed directory name %s", Path(file.name).head); } else { sha1.put(openFile(Path(file.name)).readAll()); logDebug("Hashed file contents from %s", Path(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.ver.toString(); entry["path"] = p.path.toNativeString(); newlist ~= entry; } Path 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_.versionString; 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 = Path(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 = new Package(path, PathAndFormat(), 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; Path targetPath; this(string package_, Dependency version_, Version target_version) { this.package_ = package_; this.version_ = version_; this.targetVersion = target_version; } this(string package_, Dependency version_, Path target_path) { this.package_ = package_; this.version_ = version_; this.targetPath = target_path; } } enum LocalPackageType { user, system } enum LocalPackagesFilename = "local-packages.json"; enum LocalOverridesFilename = "local-overrides.json"; private struct Repository { Path path; Path packagePath; Path[] searchPath; Package[] localPackages; PackageOverride[] overrides; this(Path path) { this.path = path; this.packagePath = path ~"packages/"; } } dub-0.9.24/source/dub/packagesupplier.d000066400000000000000000000155001267257315000177670ustar00rootroot00000000000000/** A package supplier, able to get some packages to the local FS. 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.packagesupplier; import 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 std.algorithm : filter, sort; import std.array : array; import std.conv; import std.datetime; import std.exception; import std.file; import std.string : format; import std.zip; // TODO: drop the "best package" behavior and let retrievePackage/getPackageDescription take a Version instead of Dependency /// Supplies packages, this is done by supplying the latest possible version /// which is available. interface PackageSupplier { /// Returns a hunman readable representation of the supplier @property string description(); Version[] getVersions(string package_id); /// path: absolute path to store the package (usually in a zip format) void retrievePackage(Path path, string packageId, Dependency dep, bool pre_release); /// returns the metadata for the package Json getPackageDescription(string packageId, Dependency dep, bool pre_release); /// perform cache operation void cacheOp(Path cacheDir, CacheOp op); } /// operations on package supplier cache enum CacheOp { load, store, clean, } class FileSystemPackageSupplier : PackageSupplier { private { Path m_path; } this(Path root) { m_path = root; } override @property string description() { return "file repository at "~m_path.toNativeString(); } Version[] getVersions(string package_id) { Version[] ret; foreach (DirEntry d; dirEntries(m_path.toNativeString(), package_id~"*", SpanMode.shallow)) { Path p = Path(d.name); logDebug("Entry: %s", p); enforce(to!string(p.head)[$-4..$] == ".zip"); auto vers = p.head.toString()[package_id.length+1..$-4]; logDebug("Version: %s", vers); ret ~= Version(vers); } ret.sort(); return ret; } void retrievePackage(Path path, string packageId, Dependency dep, bool pre_release) { 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 getPackageDescription(string packageId, Dependency dep, bool pre_release) { auto filename = bestPackageFile(packageId, dep, pre_release); return jsonFromZip(filename, "dub.json"); } void cacheOp(Path cacheDir, CacheOp op) { } private Path bestPackageFile(string packageId, Dependency dep, bool pre_release) { Path 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]); } } /// Client PackageSupplier using the registry available via registerVpmRegistry class RegistryPackageSupplier : PackageSupplier { private { URL m_registryUrl; struct CacheEntry { Json data; SysTime cacheTime; } CacheEntry[string] m_metadataCache; Duration m_maxCacheTime; bool m_metadataCacheDirty; } 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) { Version[] ret; Json md = getMetadata(package_id); foreach (json; md["versions"]) { auto cur = Version(cast(string)json["version"]); ret ~= cur; } ret.sort(); return ret; } void retrievePackage(Path path, string packageId, Dependency dep, bool pre_release) { import std.array : replace; Json best = getBestPackage(packageId, dep, pre_release); auto vers = best["version"].get!string; auto url = m_registryUrl ~ Path(PackagesPath~"/"~packageId~"/"~vers~".zip"); logDiagnostic("Found download URL: '%s'", url); download(url, path); } Json getPackageDescription(string packageId, Dependency dep, bool pre_release) { return getBestPackage(packageId, dep, pre_release); } void cacheOp(Path cacheDir, CacheOp op) { auto path = cacheDir ~ cacheFileName; final switch (op) { case CacheOp.store: if (!m_metadataCacheDirty) return; if (!cacheDir.existsFile()) mkdirRecurse(cacheDir.toNativeString()); // TODO: method is slow due to Json escaping writeJsonFile(path, m_metadataCache.serializeToJson()); break; case CacheOp.load: if (!path.existsFile()) return; try deserializeJson(m_metadataCache, jsonFromFile(path)); catch (Exception e) { import std.encoding; logWarn("Error loading package cache file %s: %s", path.toNativeString(), e.msg); logDebug("Full error: %s", e.toString().sanitize()); } break; case CacheOp.clean: if (path.existsFile()) removeFile(path); m_metadataCache.destroy(); break; } m_metadataCacheDirty = false; } private @property string cacheFileName() { import std.digest.md; auto hash = m_registryUrl.toString.md5Of(); return m_registryUrl.host ~ hash[0 .. $/2].toHexString().idup ~ ".json"; } 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); m_metadataCacheDirty = true; } auto url = m_registryUrl ~ Path(PackagesPath ~ "/" ~ packageId ~ ".json"); logDebug("Downloading metadata for %s", packageId); logDebug("Getting from %s", url); auto jsonData = cast(string)download(url); Json json = parseJsonString(jsonData, url.toString()); // strip readme data (to save size and time) foreach (ref v; json["versions"]) v.remove("readme"); m_metadataCache[packageId] = CacheEntry(json, now); m_metadataCacheDirty = true; return json; } private Json getBestPackage(string packageId, Dependency dep, bool pre_release) { Json md = getMetadata(packageId); Json best = null; Version bestver; foreach (json; md["versions"]) { auto cur = Version(cast(string)json["version"]); 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; } } private enum PackagesPath = "packages"; dub-0.9.24/source/dub/platform.d000066400000000000000000000053131267257315000164350ustar00rootroot00000000000000/** Determines the strings to identify the current build platform. 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.platform; import std.array; string[] determinePlatform() { auto ret = appender!(string[])(); version(Windows) ret.put("windows"); version(linux) ret.put("linux"); version(Posix) ret.put("posix"); version(OSX) ret.put("osx"); version(FreeBSD) ret.put("freebsd"); version(OpenBSD) ret.put("openbsd"); version(NetBSD) ret.put("netbsd"); version(DragonFlyBSD) ret.put("dragonflybsd"); version(BSD) ret.put("bsd"); version(Solaris) ret.put("solaris"); version(AIX) ret.put("aix"); version(Haiku) ret.put("haiku"); version(SkyOS) ret.put("skyos"); version(SysV3) ret.put("sysv3"); version(SysV4) ret.put("sysv4"); version(Hurd) ret.put("hurd"); version(Android) ret.put("android"); version(Cygwin) ret.put("cygwin"); version(MinGW) ret.put("mingw"); return ret.data; } string[] determineArchitecture() { auto ret = appender!(string[])(); version(X86) ret.put("x86"); version(X86_64) ret.put("x86_64"); version(ARM) ret.put("arm"); version(ARM_Thumb) ret.put("arm_thumb"); version(ARM_SoftFloat) ret.put("arm_softfloat"); version(ARM_HardFloat) ret.put("arm_hardfloat"); version(ARM64) ret.put("arm64"); version(PPC) ret.put("ppc"); version(PPC_SoftFP) ret.put("ppc_softfp"); version(PPC_HardFP) ret.put("ppc_hardfp"); version(PPC64) ret.put("ppc64"); version(IA64) ret.put("ia64"); version(MIPS) ret.put("mips"); version(MIPS32) ret.put("mips32"); version(MIPS64) ret.put("mips64"); version(MIPS_O32) ret.put("mips_o32"); version(MIPS_N32) ret.put("mips_n32"); version(MIPS_O64) ret.put("mips_o64"); version(MIPS_N64) ret.put("mips_n64"); version(MIPS_EABI) ret.put("mips_eabi"); version(MIPS_NoFloat) ret.put("mips_nofloat"); version(MIPS_SoftFloat) ret.put("mips_softfloat"); version(MIPS_HardFloat) ret.put("mips_hardfloat"); version(SPARC) ret.put("sparc"); version(SPARC_V8Plus) ret.put("sparc_v8plus"); version(SPARC_SoftFP) ret.put("sparc_softfp"); version(SPARC_HardFP) ret.put("sparc_hardfp"); version(SPARC64) ret.put("sparc64"); version(S390) ret.put("s390"); version(S390X) ret.put("s390x"); version(HPPA) ret.put("hppa"); version(HPPA64) ret.put("hppa64"); version(SH) ret.put("sh"); version(SH64) ret.put("sh64"); version(Alpha) ret.put("alpha"); version(Alpha_SoftFP) ret.put("alpha_softfp"); version(Alpha_HardFP) ret.put("alpha_hardfp"); return ret.data; } string determineCompiler() { version(DigitalMars) return "dmd"; else version(GNU) return "gdc"; else version(LDC) return "ldc2"; else version(SDC) return "sdc"; else return null; } dub-0.9.24/source/dub/project.d000066400000000000000000001310311267257315000162540ustar00rootroot00000000000000/** Representing a full project, with a root Package and several dependencies. 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, 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.packagesupplier; import dub.generators.generator; // todo: cleanup imports. import std.algorithm; import std.array; import std.conv; import std.datetime; import std.exception; import std.file; import std.process; import std.string; import std.typecons; import std.zip; import std.encoding : sanitize; /// Representing a full project, with a root Package and several dependencies. class Project { private { PackageManager m_packageManager; Json m_packageSettings; Package m_rootPackage; Package[] m_dependencies; Package[][Package] m_dependees; SelectedVersions m_selections; } this(PackageManager package_manager, Path 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(null, project_path); } else { pack = package_manager.getOrLoadPackage(project_path, packageFile); } this(package_manager, pack); } 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) { logDiagnostic("A " ~ SelectedVersions.defaultFile ~ " file was not found or failed to load:\n%s", e.msg); m_selections = new SelectedVersions; } } else m_selections = new SelectedVersions; reinit(); } /// Gathers information @property string info() const { if(!m_rootPackage) return "-Unrecognized application in '"~m_rootPackage.path.toNativeString()~"' (probably no dub.json in this directory)"; string s = "-Application identifier: " ~ m_rootPackage.name; s ~= "\n" ~ m_rootPackage.generateInfoString(); s ~= "\n-Retrieved dependencies:"; foreach(p; m_dependencies) s ~= "\n" ~ p.generateInfoString(); return s; } /// Gets all retrieved packages as a "packageId" = "version" associative array @property string[string] cachedPackagesIDs() const { string[string] pkgs; foreach(p; m_dependencies) pkgs[p.name] = p.vers; return pkgs; } /// List of retrieved dependency Packages @property const(Package[]) dependencies() const { return m_dependencies; } /// Main package. @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; } /** Allows iteration of the dependency tree in topological order */ 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); foreach (dn; p.dependencies.byKey.array.sort()) { auto dv = p.dependencies[dn]; // filter out dependencies not in the current configuration set if (!p.hasDependency(dn, cfg)) continue; auto dependency = getDependency(dn, dv.optional); if(dependency) perform_rec(dependency); if( ret ) return; } if( children_first ){ ret = del(p); if( ret ) return; } } perform_rec(rootpack); return ret; } return &iterator; } inout(Package) getDependency(string name, bool isOptional) inout { foreach(dp; m_dependencies) if( dp.name == name ) return dp; if(!isOptional) throw new Exception("Unknown dependency: "~name); else return null; } 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]; } 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.packageInfoFilename.toNativeString()); if (!m_rootPackage.info.buildSettings.targetName.length) { if (m_rootPackage.packageInfoFilename.head.toString().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.info.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 (dn, ds; m_rootPackage.dependencies) if (ds.isExactVersion && ds.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.", dn, SelectedVersions.defaultFile); } bool[string] visited; void validateDependenciesRec(Package pack) { foreach (name, vspec_; pack.dependencies) { if (name in visited) continue; visited[name] = true; auto basename = getBasePackageName(name); if (m_selections.hasSelectedVersion(basename)) { auto selver = m_selections.getSelectedVersion(basename); if (vspec_.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, vspec_, pack.name); } } auto deppack = getDependency(name, true); if (deppack) validateDependenciesRec(deppack); } } validateDependenciesRec(m_rootPackage); } /// Rereads the applications state. void reinit() { m_dependencies = null; m_packageManager.refresh(false); void collectDependenciesRec(Package pack) { logDebug("Collecting dependencies for %s", pack.name); foreach (name, vspec_; pack.dependencies) { Dependency vspec = vspec_; Package p; if (!vspec.path.empty) { Path path = vspec.path; if (!path.absolute) path = pack.path ~ path; logDiagnostic("Adding local %s", path); p = m_packageManager.getOrLoadPackage(path, PathAndFormat.init, true); if (p.parentPackage !is null) { logWarn("Sub package %s must be referenced using the path to it's parent package.", name); p = p.parentPackage; } if (name.canFind(':')) p = m_packageManager.getSubPackage(p, getSubPackageName(name), false); enforce(p.name == name, format("Path based dependency %s is referenced with a wrong name: %s vs. %s", path.toNativeString(), name, p.name)); } if (!p) { auto basename = getBasePackageName(name); if (name == m_rootPackage.basePackage.name) { vspec = Dependency(m_rootPackage.ver); p = m_rootPackage.basePackage; } else if (basename == m_rootPackage.basePackage.name) { vspec = Dependency(m_rootPackage.ver); try p = m_packageManager.getSubPackage(m_rootPackage.basePackage, getSubPackageName(name), false); catch (Exception e) { logDiagnostic("Error getting sub package %s: %s", name, e.msg); continue; } } else if (m_selections.hasSelectedVersion(basename)) { vspec = m_selections.getSelectedVersion(basename); p = m_packageManager.getBestPackage(name, vspec); } 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); p = m_packageManager.getSubPackage(bp, getSubPackageName(name), false); } else { logDiagnostic("Version selection for dependency %s (%s) of %s is missing.", basename, name, pack.name); continue; } } if (!p) { logDiagnostic("Missing dependency %s %s of %s", name, vspec, pack.name); continue; } if (!m_dependencies.canFind(p)) { logDiagnostic("Found dependency %s %s", name, vspec.toString()); m_dependencies ~= p; p.warnOnSpecialCompilerFlags(); collectDependenciesRec(p); } m_dependees[p] ~= pack; //enforce(p !is null, "Failed to resolve dependency "~name~" "~vspec.toString()); } } collectDependenciesRec(m_rootPackage); } /// Returns the applications name. @property string name() const { return m_rootPackage ? m_rootPackage.name : "app"; } @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.dependencies.byKey) parents[d] ~= p.name; size_t createConfig(string pack, string config) { foreach (i, v; configs) if (v.pack == pack && v.config == config) return i; 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); configs = configs.remove(i); edges = edges.filter!(e => e.from != i && e.to != i).array(); foreach (ref e; edges) { if (e.from > i) e.from--; if (e.to > i) e.to--; } } 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; // 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 (dn; p.dependencies.byKey) { auto dp = getDependency(dn, true); if (!dp) continue; determineAllConfigs(dp); } // for each configuration, determine the configurations usable for the dependencies outer: foreach (c; p.getPlatformConfigurations(platform, p is m_rootPackage && allow_non_library)) { string[][string] depconfigs; foreach (dn; p.dependencies.byKey) { auto dp = getDependency(dn, true); if (!dp) continue; string[] cfgs; auto subconf = p.getSubConfiguration(c, dp, platform); if (!subconf.empty) cfgs = [subconf]; else cfgs = dp.getPlatformConfigurations(platform); cfgs = cfgs.filter!(c => haveConfig(dn, 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); continue outer; } depconfigs[dn] = cfgs; } // add this configuration to the graph size_t cidx = createConfig(p.name, c); foreach (dn; p.dependencies.byKey) foreach (sc; depconfigs.get(dn, null)) createEdge(cidx, createConfig(dn, sc)); } } 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; for (size_t i = 0; i < configs.length; ) { if (!isReachableByAllParentPacks(i)) { logDebug("NOT REACHABLE by (%s):", parents[configs[i].pack]); removeConfig(i); changed = true; } else i++; } // when all edges are cleaned up, pick one package and remove all but one config if (!changed) { foreach (p; getTopologicalPackageList()) { size_t cnt = 0; for (size_t i = 0; i < configs.length; ) { if (configs[i].pack == p.name) { if (++cnt > 1) { logDebug("NON-PRIMARY:"); removeConfig(i); } else i++; } else 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) { 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. * platform = The platform 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 BuildPlatform platform, string config, in Package root_package = null, bool shallow = false) const { auto configs = getPackageConfigs(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(platform, configs[pkg.name]); if (psettings.targetType != TargetType.none) { if (shallow && pkg !is m_rootPackage) psettings.sourceFiles = null; processVars(dst, this, pkg, psettings); 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, true); if (psettings.mainSourceFile.length) dst.mainSourceFile = processVars(psettings.mainSourceFile, this, pkg, true); } } // always add all version identifiers of all packages foreach (pkg; this.getTopologicalPackageList(false, null, configs)) { auto psettings = pkg.getBuildSettings(platform, configs[pkg.name]); dst.addVersions(psettings.versions); } } void addBuildTypeSettings(ref BuildSettings dst, in BuildPlatform platform, string build_type) { bool usedefflags = !(dst.requirements & BuildRequirement.noDefaultFlags); if (usedefflags) { BuildSettings btsettings; m_rootPackage.addBuildTypeSettings(btsettings, platform, build_type); processVars(dst, this, m_rootPackage, btsettings); } } /// Determines if the given dependency is already indirectly referenced by other dependencies of pack. bool isRedundantDependency(in Package pack, in Package dependency) const { foreach (dep; pack.dependencies.byKey) { auto dp = getDependency(dep, true); if (!dp) continue; if (dp is dependency) continue; foreach (ddp; getTopologicalPackageList(false, dp)) if (ddp is dependency) return true; } return false; } /*bool iterateDependencies(bool delegate(Package pack, string dep_name, Dependency dep_spec) del) { bool all_found = true; bool[string] visited; void iterate(Package pack) { if (pack.name in visited) return; visited[pack.name] = true; foreach (dn, ds; pack.dependencies) { auto dep = del(pack, dn, ds); if (dep) iterateDependencies(dep); else all_found = false; } } return all_found; }*/ /// Outputs a build description of the project, including its dependencies. ProjectDescription describe(BuildPlatform platform, string config, string build_type = null) { import dub.generators.targetdescription; // store basic build parameters ProjectDescription ret; ret.rootPackage = m_rootPackage.name; ret.configuration = config; ret.buildType = build_type; ret.compiler = platform.compiler; ret.architecture = platform.architecture; ret.platform = platform.platform; // collect high level information about projects (useful for IDE display) auto configs = getPackageConfigs(platform, config); ret.packages ~= m_rootPackage.describe(platform, config); foreach (dep; m_dependencies) ret.packages ~= dep.describe(platform, configs[dep.name]); foreach (p; getTopologicalPackageList(false, null, configs)) ret.packages[ret.packages.countUntil!(pp => pp.name == p.name)].active = true; if (build_type.length) { // collect build target information (useful for build tools) GeneratorSettings settings; settings.platform = platform; settings.compiler = getCompiler(platform.compilerBinary); settings.config = config; settings.buildType = build_type; 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; } /// ditto deprecated void describe(ref Json dst, BuildPlatform platform, string config) { auto desc = describe(platform, config); foreach (string key, value; desc.serializeToJson()) dst[key] = value; } 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, 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, 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; 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 == "targetType" || attributeName == "requirements" || attributeName == "options"; 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 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 "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-format=list."); break; case "requirements": enforce(false, "--data=requirements can only be used with --data-format=list. 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 "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 "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(BuildPlatform platform, string config, string buildType, string[] requestedData, Compiler formattingCompiler, bool nullDelim) { auto projectDescription = describe(platform, config, buildType); auto configs = getPackageConfigs(platform, config); PackageDescription packageDescription; foreach (pack; projectDescription.packages) { if (pack.name == projectDescription.rootPackage) packageDescription = pack; } // Copy linker files from sourceFiles to linkerFiles auto target = projectDescription.lookupTarget(projectDescription.rootPackage); foreach (file; target.buildSettings.sourceFiles.filter!(isLinkerFile)) target.buildSettings.addLinkerFiles(file); // Remove linker files from sourceFiles target.buildSettings.sourceFiles = target.buildSettings.sourceFiles .filter!(a => !isLinkerFile(a)) .array(); projectDescription.lookupTarget(projectDescription.rootPackage) = target; // Genrate results if (formattingCompiler) { // Format for a compiler return [ requestedData .map!(dataName => listBuildSetting(platform, configs, projectDescription, dataName, formattingCompiler, nullDelim)) .join().join(nullDelim? "\0" : " ") ]; } else { // Format list-style return requestedData .map!(dataName => listBuildSetting(platform, configs, projectDescription, dataName, null, nullDelim)) .joiner([""]) // Blank entry between each type of requestedData .array(); } } /// Outputs the import paths for the project, including its dependencies. string[] listImportPaths(BuildPlatform platform, string config, string buildType, bool nullDelim) { auto projectDescription = describe(platform, config, buildType); return listBuildSetting!"importPaths"(platform, config, projectDescription, null, nullDelim); } /// Outputs the string import paths for the project, including its dependencies. string[] listStringImportPaths(BuildPlatform platform, string config, string buildType, bool nullDelim) { auto projectDescription = describe(platform, config, buildType); return listBuildSetting!"stringImportPaths"(platform, config, projectDescription, null, nullDelim); } 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); } bool isUpgradeCacheUpToDate() { try { auto datestr = m_packageSettings["dub"].opt!(Json[string]).get("lastUpgrade", Json("")).get!string; if (!datestr.length) return false; auto date = SysTime.fromISOExtString(datestr); if ((Clock.currTime() - date) > 1.days) return false; return true; } catch (Exception t) { logDebug("Failed to get the last upgrade time: %s", t.msg); return false; } } Dependency[string] getUpgradeCache() { try { Dependency[string] ret; foreach (string p, d; m_packageSettings["dub"].opt!(Json[string]).get("cachedUpgrades", Json.emptyObject)) ret[p] = SelectedVersions.dependencyFromJson(d); return ret; } catch (Exception t) { logDebug("Failed to get cached upgrades: %s", t.msg); return null; } } 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() { // 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."); } } } /// Actions to be performed by the dub struct Action { enum Type { fetch, remove, conflict, failure } immutable { Type type; string packageId; PlacementLocation location; Dependency vers; Version existingVersion; } const Package pack; const Dependency[string] issuer; static Action get(string pkg, PlacementLocation location, in Dependency dep, Dependency[string] context, Version old_version = Version.UNKNOWN) { return Action(Type.fetch, pkg, location, dep, context, old_version); } static Action remove(Package pkg, Dependency[string] context) { return Action(Type.remove, pkg, context); } static Action conflict(string pkg, in Dependency dep, Dependency[string] context) { return Action(Type.conflict, pkg, PlacementLocation.user, dep, context); } static Action failure(string pkg, in Dependency dep, Dependency[string] context) { return Action(Type.failure, pkg, PlacementLocation.user, dep, context); } private this(Type id, string pkg, PlacementLocation location, in Dependency d, Dependency[string] issue, Version existing_version = Version.UNKNOWN) { this.type = id; this.packageId = pkg; this.location = location; this.vers = d; this.issuer = issue; this.existingVersion = existing_version; } private this(Type id, Package pkg, Dependency[string] issue) { pack = pkg; type = id; packageId = pkg.name; vers = cast(immutable)Dependency(pkg.ver); issuer = issue; } string toString() const { return to!string(type) ~ ": " ~ packageId ~ ", " ~ to!string(vers); } } /// Indicates where a package has been or should be placed to. enum PlacementLocation { /// Packages retrived 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 } /// The default placement location of fetched packages. Can be changed by --local or --system. auto defaultPlacementLocation = PlacementLocation.user; void processVars(ref BuildSettings dst, in Project project, in Package pack, BuildSettings settings, bool include_target_settings = false) { dst.addDFlags(processVars(project, pack, settings.dflags)); dst.addLFlags(processVars(project, pack, settings.lflags)); dst.addLibs(processVars(project, pack, settings.libs)); dst.addSourceFiles(processVars(project, pack, settings.sourceFiles, true)); dst.addImportFiles(processVars(project, pack, settings.importFiles, true)); dst.addStringImportFiles(processVars(project, pack, settings.stringImportFiles, true)); dst.addCopyFiles(processVars(project, pack, settings.copyFiles, true)); dst.addVersions(processVars(project, pack, settings.versions)); dst.addDebugVersions(processVars(project, pack, settings.debugVersions)); dst.addImportPaths(processVars(project, pack, settings.importPaths, true)); dst.addStringImportPaths(processVars(project, pack, settings.stringImportPaths, true)); dst.addPreGenerateCommands(processVars(project, pack, settings.preGenerateCommands)); dst.addPostGenerateCommands(processVars(project, pack, settings.postGenerateCommands)); dst.addPreBuildCommands(processVars(project, pack, settings.preBuildCommands)); dst.addPostBuildCommands(processVars(project, pack, settings.postBuildCommands)); dst.addRequirements(settings.requirements); dst.addOptions(settings.options); if (include_target_settings) { dst.targetType = settings.targetType; dst.targetPath = processVars(settings.targetPath, project, pack, true); dst.targetName = settings.targetName; if (!settings.workingDirectory.empty) dst.workingDirectory = processVars(settings.workingDirectory, project, pack, true); if (settings.mainSourceFile.length) dst.mainSourceFile = processVars(settings.mainSourceFile, project, pack, true); } } private string[] processVars(in Project project, in Package pack, string[] vars, bool are_paths = false) { auto ret = appender!(string[])(); processVars(ret, project, pack, vars, are_paths); return ret.data; } private void processVars(ref Appender!(string[]) dst, in Project project, in Package pack, string[] vars, bool are_paths = false) { foreach (var; vars) dst.put(processVars(var, project, pack, are_paths)); } private string processVars(string var, in Project project, in Package pack, bool is_path) { auto idx = std.string.indexOf(var, '$'); if (idx >= 0) { auto vres = appender!string(); while (idx >= 0) { if (idx+1 >= var.length) break; if (var[idx+1] == '$') { vres.put(var[0 .. idx+1]); var = var[idx+2 .. $]; } else { vres.put(var[0 .. idx]); var = var[idx+1 .. $]; size_t idx2 = 0; while( idx2 < var.length && isIdentChar(var[idx2]) ) idx2++; auto varname = var[0 .. idx2]; var = var[idx2 .. $]; vres.put(getVariable(varname, project, pack)); } idx = std.string.indexOf(var, '$'); } vres.put(var); var = vres.data; } if (is_path) { auto p = Path(var); if (!p.absolute) { logDebug("Fixing relative path: %s ~ %s", pack.path.toNativeString(), p.toNativeString()); return (pack.path ~ p).toNativeString(); } else return p.toNativeString(); } else return var; } private string getVariable(string name, in Project project, in Package pack) { if (name == "PACKAGE_DIR") return pack.path.toNativeString(); if (name == "ROOT_PACKAGE_DIR") return project.rootPackage.path.toNativeString(); if (name.endsWith("_PACKAGE_DIR")) { auto pname = name[0 .. $-12]; foreach (prj; project.getTopologicalPackageList()) if (prj.name.toUpper().replace("-", "_") == pname) return prj.path.toNativeString(); } auto envvar = environment.get(name); if (envvar !is null) return envvar; throw new Exception("Invalid variable: "~name); } private bool isIdentChar(dchar ch) { return ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9' || ch == '_'; } string stripDlangSpecialChars(string s) { import std.array; import std.uni; auto ret = appender!string(); foreach(ch; s) ret.put(isIdentChar(ch) ? ch : '_'); return ret.data; } 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 } enum defaultFile = "dub.selections.json"; this() {} this(Json data) { deserialize(data); m_dirty = false; } this(Path path) { auto json = jsonFromFile(path); deserialize(json); m_dirty = false; } @property string[] selectedPackages() const { return m_selections.keys; } @property bool dirty() const { return m_dirty; } void clear() { m_selections = null; m_dirty = true; } void set(SelectedVersions versions) { m_selections = versions.m_selections.dup; m_dirty = true; } 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; } void selectVersion(string package_id, Path 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; } void deselectVersion(string package_id) { m_selections.remove(package_id); m_dirty = true; } bool hasSelectedVersion(string packageId) const { return (packageId in m_selections) !is null; } Dependency getSelectedVersion(string packageId) const { enforce(hasSelectedVersion(packageId)); return m_selections[packageId].dep; } void save(Path path) { Json json = serialize(); auto file = openFile(path, FileMode.createTrunc); scope(exit) file.close(); file.writePrettyJsonString(json); file.put('\n'); m_dirty = 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(Path(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-0.9.24/source/dub/recipe/000077500000000000000000000000001267257315000157115ustar00rootroot00000000000000dub-0.9.24/source/dub/recipe/io.d000066400000000000000000000024651267257315000164740ustar00rootroot00000000000000module dub.recipe.io; import dub.recipe.packagerecipe; import dub.internal.vibecompat.inet.path; /** Reads a package recipe from a file. */ PackageRecipe readPackageRecipe(string filename, string parent_name = null) { return readPackageRecipe(Path(filename), parent_name); } /// ditto PackageRecipe readPackageRecipe(Path file, string parent_name = null) { import dub.internal.utils : stripUTF8Bom; import dub.internal.vibecompat.core.file : openFile, FileMode; string text; { auto f = openFile(file.toNativeString(), FileMode.read); scope(exit) f.close(); text = stripUTF8Bom(cast(string)f.readAll()); } return parsePackageRecipe(text, file.toNativeString(), parent_name); } /** Parses an in-memory package recipe. */ PackageRecipe parsePackageRecipe(string contents, string filename, string parent_name = null) { import std.algorithm : endsWith; import dub.internal.vibecompat.data.json; import dub.recipe.json : parseJson; import dub.recipe.sdl : parseSDL; PackageRecipe ret; if (filename.endsWith(".json")) dub.recipe.json.parseJson(ret, parseJsonString(contents, filename), parent_name); else if (filename.endsWith(".sdl")) dub.recipe.sdl.parseSDL(ret, contents, parent_name, filename); else assert(false, "readPackageRecipe called with filename with unknown extension: "~filename); return ret; } dub-0.9.24/source/dub/recipe/json.d000066400000000000000000000264251267257315000170400ustar00rootroot00000000000000/** 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 "-ddoxFilterArgs": recipe.ddoxFilterArgs = deserializeJson!(string[])(value); 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.ddoxFilterArgs.empty) ret["-ddoxFilterArgs"] = recipe.ddoxFilterArgs.serializeToJson(); 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."); BuildSettingsTemplate bs; 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 "versions": bs.versions[suffix] = deserializeJson!(string[])(value); break; case "debugVersions": bs.debugVersions[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 "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; } } } 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; 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.versions) ret["versions"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.debugVersions) ret["debugVersions"~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.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; } dub-0.9.24/source/dub/recipe/packagerecipe.d000066400000000000000000000201741267257315000206450ustar00rootroot00000000000000/** 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.dependency; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.url; import std.algorithm : sort; import std.array : join, split; import std.exception : enforce; import std.file; import std.range; /** 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", wich in turn is a sub package of "packa". */ string[] getSubPackagePath(string package_name) { 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) { return package_name.getSubPackagePath()[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) { return getSubPackagePath(package_name)[1 .. $].join(":"); } /** 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; BuildSettingsTemplate buildSettings; ConfigurationInfo[] configurations; BuildSettingsTemplate[string] buildTypes; SubPackage[] subPackages; @property const(Dependency)[string] dependencies() const { Dependency[string] ret; foreach (n, d; this.buildSettings.dependencies) ret[n] = d; foreach (ref c; configurations) foreach (n, d; c.buildSettings.dependencies) ret[n] = d; return ret; } inout(ConfigurationInfo) getConfiguration(string name) inout { foreach (c; configurations) if (c.name == name) return c; throw new Exception("Unknown configuration: "~name); } } struct SubPackage { string path; PackageRecipe recipe; } /// 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] versions; string[][string] debugVersions; string[][string] importPaths; string[][string] stringImportPaths; string[][string] preGenerateCommands; string[][string] postGenerateCommands; string[][string] preBuildCommands; string[][string] postBuildCommands; BuildRequirements[string] buildRequirements; BuildOptions[string] buildOptions; /// Constructs a BuildSettings object from this template. void getPlatformSettings(ref BuildSettings dst, in BuildPlatform platform, Path 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) { dst.mainSourceFile = this.mainSourceFile; dst.addSourceFiles(this.mainSourceFile); } void collectFiles(string method)(in string[][string] paths_map, string pattern) { foreach (suffix, paths; paths_map) { if (!platform.matchesSpecification(suffix)) continue; foreach (spath; paths) { enforce(!spath.empty, "Paths must not be empty strings."); auto path = Path(spath); if (!path.absolute) path = base_path ~ path; if (!existsFile(path) || !isDir(path.toNativeString())) { 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] == '.' || isDir(d.name)) continue; auto src = Path(d.name).relativeTo(base_path); __traits(getMember, dst, method)(src.toNativeString()); } } } } // collect files from all source/import folders collectFiles!"addSourceFiles"(sourcePaths, "*.d"); collectFiles!"addImportFiles"(importPaths, "*.{d,di}"); dst.removeImportFiles(dst.sourceFiles); collectFiles!"addStringImportFiles"(stringImportPaths, "*"); // ensure a deterministic order of files as passed to the compiler dst.sourceFiles.sort(); 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!("versions", "addVersions")(dst, platform); getPlatformSetting!("debugVersions", "addDebugVersions")(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!("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); } } } dub-0.9.24/source/dub/recipe/sdl.d000066400000000000000000000367631267257315000166570ustar00rootroot00000000000000/** 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.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 "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 "x:ddoxFilterArgs": recipe.ddoxFilterArgs ~= n.stringArrayTagValue; break; } } enforce(recipe.name.length > 0, "The package \"name\" field is missing or empty."); string full_name = parent_name.length ? parent_name ~ ":" ~ recipe.name : recipe.name; // parse general build settings parseBuildSettings(sdl, recipe.buildSettings, full_name); // parse configurations recipe.configurations.length = configs.length; foreach (i, n; configs) 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); } } } private void parseBuildSettings(Tag settings, ref BuildSettingsTemplate bs, string package_name) { foreach (setting; settings.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 "versions": setting.parsePlatformStringArray(bs.versions); break; case "debugVersions": setting.parsePlatformStringArray(bs.debugVersions); 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 "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) { auto pkg = expandPackageName(t.values[0].get!string, package_name, t); enforce(pkg !in bs.dependencies, "The dependency '"~pkg~"' is specified more than once." ); Dependency dep = Dependency.ANY; auto attrs = t.attributes; auto pv = "version" in attrs; 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 = Path(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; bs.dependencies[pkg] = dep; } 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 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 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; foreach (v; t.values) dst[platform] ~= v.get!string; } 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, 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" 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" } x:ddoxFilterArgs "-arg1" "-arg2" x:ddoxFilterArgs "-arg3" 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" versions "version1" "version2" versions "version3" debugVersions "debug1" "debug2" debugVersions "debug3" 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" dflags "df1" "df2" dflags "df3" lflags "lf1" "lf2" lflags "lf3" `; PackageRecipe rec; parseSDL(rec, sdl, null, "testfile"); 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.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.dependencies.length == 1); assert("projectname:subpackage1" in rec.subPackages[1].recipe.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.ddoxFilterArgs == ["-arg1", "-arg2", "-arg3"], rec.ddoxFilterArgs.to!string); assert(rec.buildSettings.dependencies.length == 2); assert(rec.buildSettings.dependencies["projectname:subpackage1"].optional == false); assert(rec.buildSettings.dependencies["projectname:subpackage1"].path == Path(".")); assert(rec.buildSettings.dependencies["somedep"].versionString == "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.versions == ["": ["version1", "version2", "version3"]]); assert(rec.buildSettings.debugVersions == ["": ["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.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")); }dub-0.9.24/source/dub/semver.d000066400000000000000000000235621267257315000161200ustar00rootroot00000000000000/** Implementes version validation and comparison according to the semantic versioning specification. Copyright: © 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.semver; import std.range; import std.string; import std.algorithm : max; import std.conv; /* General format of SemVer: a.b.c[-x.y...][+x.y...] a/b/c must be integer numbers with no leading zeros x/y/... must be either numbers or identifiers containing only ASCII alphabetic characters or hyphens */ /** Validates a version string according to the SemVer specification. */ bool isValidVersion(string ver) { // 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")); } bool isPreReleaseVersion(string ver) 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]); } /** Compares the precedence of two SemVer version strings. The version strings must be validated using isValidVersion() before being passed to this function. */ int compareVersions(string a, string b) { // compare a.b.c numerically if (auto ret = compareNumber(a, b)) return ret; assert(a[0] == '.' && b[0] == '.'); a.popFront(); b.popFront(); if (auto ret = compareNumber(a, b)) return ret; assert(a[0] == '.' && b[0] == '.'); a.popFront(); b.popFront(); 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.popFront(); b.popFront(); 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 { 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"); } /** Given version string, increments the next to last version number. Prerelease and build metadata information is ignored. @param ver Does not need to be a valid semver version. @return Valid semver version 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) Examples: 1.5 -> 2.0 1.5.67 -> 1.6.0 1.5.67-a -> 1.6.0 */ string bumpVersion(string ver) { // 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 = split(ver, "."); 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")); } /** Takes a abbreviated version and expands it to a valid SemVer version. E.g. "1.0" -> "1.0.0" */ string expandVersion(string ver) { auto mi = ver.indexOfAny("+-"); auto sub = ""; if (mi > 0) { sub = ver[mi..$]; ver = ver[0..mi]; } auto splitted = split(ver, "."); 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) { bool anumber = true; bool bnumber = true; bool aempty = true, bempty = true; int res = 0; while (true) { if (a.front != b.front && res == 0) res = a.front - b.front; if (anumber && (a.front < '0' || a.front > '9')) anumber = false; if (bnumber && (b.front < '0' || b.front > '9')) bnumber = false; a.popFront(); b.popFront(); aempty = a.empty || a.front == '.' || a.front == '+'; bempty = b.empty || b.front == '.' || b.front == '+'; 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) { int res = 0; while (true) { if (a.front != b.front && res == 0) res = a.front - b.front; a.popFront(); b.popFront(); auto aempty = a.empty || (a.front < '0' || a.front > '9'); auto bempty = b.empty || (b.front < '0' || b.front > '9'); if (aempty != bempty) return bempty - aempty; if (aempty) return res; } } private bool isValidIdentifierChain(string str, bool allow_leading_zeros = false) { 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) { 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) { 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 sizediff_t indexOfAny(string str, in char[] chars) { sizediff_t ret = -1; foreach (ch; chars) { auto idx = str.indexOf(ch); if (idx >= 0 && (ret < 0 || idx < ret)) ret = idx; } return ret; } dub-0.9.24/source/dub/version_.d000066400000000000000000000000641267257315000164330ustar00rootroot00000000000000module dub.version_; enum dubVersion = "v0.9.24"; dub-0.9.24/test/000077500000000000000000000000001267257315000133475ustar00rootroot00000000000000dub-0.9.24/test/.gitignore000066400000000000000000000003661267257315000153440ustar00rootroot00000000000000*.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 dub-0.9.24/test/0-init-fail-json.sh000077500000000000000000000004631267257315000166710ustar00rootroot00000000000000#!/bin/bash packname="0-init-fail-pack" deps="logger PACKAGE_DONT_EXIST" # would be very unlucky if it does exist... $DUB init $packname $deps -f json function cleanup { rm -rf $packname } if [ -e $packname/dub.json ]; then # package is there, it should have failed cleanup exit 1 fi exit 0 dub-0.9.24/test/0-init-fail.sh000077500000000000000000000004521267257315000157200ustar00rootroot00000000000000#!/bin/bash packname="0-init-fail-pack" deps="logger PACKAGE_DONT_EXIST" # would be very unlucky if it does exist... $DUB init $packname $deps function cleanup { rm -rf $packname } if [ -e $packname/dub.sdl ]; then # package is there, it should have failed cleanup exit 1 fi exit 0 dub-0.9.24/test/0-init-multi-json.sh000077500000000000000000000011511267257315000171030ustar00rootroot00000000000000#!/bin/bash packname="0-init-multi-pack" deps="openssl logger" type="vibe.d" $DUB init $packname $deps --type=$type -f json function cleanup { rm -rf $packname } if [ ! -e $packname/dub.json ]; then # it failed, exit 1 exit 1 else # check if resulting dub.json has all dependancies 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 echo "$ele not in $packname/dub.json" cleanup exit 1 fi done cleanup exit 0 fi dub-0.9.24/test/0-init-multi.sh000077500000000000000000000011351267257315000161360ustar00rootroot00000000000000#!/bin/bash packname="0-init-multi-pack" deps="openssl logger" type="vibe.d" $DUB init $packname $deps --type=$type function cleanup { rm -rf $packname } if [ ! -e $packname/dub.sdl ]; then # it failed, exit 1 exit 1 else # check if resulting dub.sdl has all dependancies 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 echo "$ele not in $packname/dub.sdl" cleanup exit 1 fi done cleanup exit 0 fi dub-0.9.24/test/0-init-simple-json.sh000077500000000000000000000003161267257315000172440ustar00rootroot00000000000000#!/bin/bash packname="0-init-simple-pack" $DUB init $packname -f json function cleanup { rm -rf $packname } if [ ! -e $packname/dub.json ]; then # it failed cleanup exit 1 fi cleanup exit 0 dub-0.9.24/test/0-init-simple.sh000077500000000000000000000003051267257315000162730ustar00rootroot00000000000000#!/bin/bash packname="0-init-simple-pack" $DUB init $packname function cleanup { rm -rf $packname } if [ ! -e $packname/dub.sdl ]; then # it failed cleanup exit 1 fi cleanup exit 0 dub-0.9.24/test/1-dynLib-simple/000077500000000000000000000000001267257315000162155ustar00rootroot00000000000000dub-0.9.24/test/1-dynLib-simple/.no_build000066400000000000000000000000601267257315000200050ustar00rootroot00000000000000Remove me when bug with dynamic libs get fixed. dub-0.9.24/test/1-dynLib-simple/dub.json000066400000000000000000000001041267257315000176550ustar00rootroot00000000000000{ "name": "dynlib-simple", "targetType": "dynamicLibrary" } dub-0.9.24/test/1-dynLib-simple/source/000077500000000000000000000000001267257315000175155ustar00rootroot00000000000000dub-0.9.24/test/1-dynLib-simple/source/dynlib/000077500000000000000000000000001267257315000207765ustar00rootroot00000000000000dub-0.9.24/test/1-dynLib-simple/source/dynlib/app.d000066400000000000000000000001221267257315000217160ustar00rootroot00000000000000module dynlib.app; import std.stdio; void entry() { writeln(__FUNCTION__); } dub-0.9.24/test/1-exec-simple-package-json/000077500000000000000000000000001267257315000202605ustar00rootroot00000000000000dub-0.9.24/test/1-exec-simple-package-json/package.json000066400000000000000000000000761267257315000225510ustar00rootroot00000000000000{ "name": "exec-simple", "targetType": "executable" } dub-0.9.24/test/1-exec-simple-package-json/source/000077500000000000000000000000001267257315000215605ustar00rootroot00000000000000dub-0.9.24/test/1-exec-simple-package-json/source/app.d000066400000000000000000000000761267257315000225100ustar00rootroot00000000000000import std.stdio; void main() { writeln(__FUNCTION__); } dub-0.9.24/test/1-exec-simple/000077500000000000000000000000001267257315000157205ustar00rootroot00000000000000dub-0.9.24/test/1-exec-simple/dub.json000066400000000000000000000000761267257315000173700ustar00rootroot00000000000000{ "name": "exec-simple", "targetType": "executable" } dub-0.9.24/test/1-exec-simple/source/000077500000000000000000000000001267257315000172205ustar00rootroot00000000000000dub-0.9.24/test/1-exec-simple/source/app.d000066400000000000000000000000761267257315000201500ustar00rootroot00000000000000import std.stdio; void main() { writeln(__FUNCTION__); } dub-0.9.24/test/1-sourceLib-simple/000077500000000000000000000000001267257315000167235ustar00rootroot00000000000000dub-0.9.24/test/1-sourceLib-simple/.no_build000066400000000000000000000000001267257315000205050ustar00rootroot00000000000000dub-0.9.24/test/1-sourceLib-simple/dub.json000066400000000000000000000001061267257315000203650ustar00rootroot00000000000000{ "name": "sourcelib-simple", "targetType": "sourceLibrary" } dub-0.9.24/test/1-sourceLib-simple/source/000077500000000000000000000000001267257315000202235ustar00rootroot00000000000000dub-0.9.24/test/1-sourceLib-simple/source/sourcelib/000077500000000000000000000000001267257315000222125ustar00rootroot00000000000000dub-0.9.24/test/1-sourceLib-simple/source/sourcelib/app.d000066400000000000000000000001251267257315000231350ustar00rootroot00000000000000module sourcelib.app; import std.stdio; void entry() { writeln(__FUNCTION__); } dub-0.9.24/test/1-staticLib-simple/000077500000000000000000000000001267257315000167125ustar00rootroot00000000000000dub-0.9.24/test/1-staticLib-simple/.no_run000066400000000000000000000000001267257315000202010ustar00rootroot00000000000000dub-0.9.24/test/1-staticLib-simple/dub.json000066400000000000000000000001061267257315000203540ustar00rootroot00000000000000{ "name": "staticlib-simple", "targetType": "staticLibrary" } dub-0.9.24/test/1-staticLib-simple/source/000077500000000000000000000000001267257315000202125ustar00rootroot00000000000000dub-0.9.24/test/1-staticLib-simple/source/staticlib/000077500000000000000000000000001267257315000221705ustar00rootroot00000000000000dub-0.9.24/test/1-staticLib-simple/source/staticlib/app.d000066400000000000000000000001251267257315000231130ustar00rootroot00000000000000module staticlib.app; import std.stdio; void entry() { writeln(__FUNCTION__); } dub-0.9.24/test/2-dynLib-dep/000077500000000000000000000000001267257315000154755ustar00rootroot00000000000000dub-0.9.24/test/2-dynLib-dep/dub.json000066400000000000000000000001651267257315000171440ustar00rootroot00000000000000{ "name": "dynlib-dep", "dependencies": { "dynlib-simple": { "path": "../1-dynLib-simple/" } } } dub-0.9.24/test/2-dynLib-dep/source/000077500000000000000000000000001267257315000167755ustar00rootroot00000000000000dub-0.9.24/test/2-dynLib-dep/source/app.d000066400000000000000000000000751267257315000177240ustar00rootroot00000000000000module app; import dynlib.app; void main() { entry(); } dub-0.9.24/test/2-sourceLib-dep/000077500000000000000000000000001267257315000162035ustar00rootroot00000000000000dub-0.9.24/test/2-sourceLib-dep/dub.json000066400000000000000000000002661267257315000176540ustar00rootroot00000000000000{ "name": "sourcelib-dep", "description": "Testing sourceLibrary dependency.", "dependencies": { "sourcelib-simple": { "path": "../1-sourceLib-simple/" } } } dub-0.9.24/test/2-sourceLib-dep/source/000077500000000000000000000000001267257315000175035ustar00rootroot00000000000000dub-0.9.24/test/2-sourceLib-dep/source/app.d000066400000000000000000000001001267257315000204170ustar00rootroot00000000000000module app; import sourcelib.app; void main() { entry(); } dub-0.9.24/test/2-staticLib-dep/000077500000000000000000000000001267257315000161725ustar00rootroot00000000000000dub-0.9.24/test/2-staticLib-dep/dub.json000066400000000000000000000002661267257315000176430ustar00rootroot00000000000000{ "name": "staticlib-dep", "description": "Testing staticLibrary dependency.", "dependencies": { "staticlib-simple": { "path": "../1-staticLib-simple/" } } } dub-0.9.24/test/2-staticLib-dep/source/000077500000000000000000000000001267257315000174725ustar00rootroot00000000000000dub-0.9.24/test/2-staticLib-dep/source/app.d000066400000000000000000000001001267257315000204060ustar00rootroot00000000000000module app; import staticlib.app; void main() { entry(); } dub-0.9.24/test/3-copyFiles/000077500000000000000000000000001267257315000154445ustar00rootroot00000000000000dub-0.9.24/test/3-copyFiles/data/000077500000000000000000000000001267257315000163555ustar00rootroot00000000000000dub-0.9.24/test/3-copyFiles/data/file_to_copy.txt000066400000000000000000000000311267257315000215630ustar00rootroot00000000000000file_to_copy.txt content dub-0.9.24/test/3-copyFiles/data/file_to_copy_mask1.txt000066400000000000000000000000361267257315000226640ustar00rootroot00000000000000file_to_copy_mask1.txt contentdub-0.9.24/test/3-copyFiles/data/file_to_copy_mask2.txt000066400000000000000000000000371267257315000226660ustar00rootroot00000000000000file_to_copy_mask2.txt content dub-0.9.24/test/3-copyFiles/data/res/000077500000000000000000000000001267257315000171465ustar00rootroot00000000000000dub-0.9.24/test/3-copyFiles/data/res/.nocopy/000077500000000000000000000000001267257315000205335ustar00rootroot00000000000000dub-0.9.24/test/3-copyFiles/data/res/.nocopy/file_inside_dot_prefixed_dir.txt000066400000000000000000000000151267257315000271340ustar00rootroot00000000000000some content dub-0.9.24/test/3-copyFiles/data/res/hdpi/000077500000000000000000000000001267257315000200725ustar00rootroot00000000000000dub-0.9.24/test/3-copyFiles/data/res/hdpi/file1.txt000066400000000000000000000000231267257315000216260ustar00rootroot00000000000000hdpi/file1 content dub-0.9.24/test/3-copyFiles/data/res/hdpi/file2.txt000066400000000000000000000000231267257315000216270ustar00rootroot00000000000000hdpi/file2 content dub-0.9.24/test/3-copyFiles/data/res/hdpi/file3.txt000066400000000000000000000000231267257315000216300ustar00rootroot00000000000000hdpi/file3 content dub-0.9.24/test/3-copyFiles/data/res/hdpi/nested_dir/000077500000000000000000000000001267257315000222125ustar00rootroot00000000000000dub-0.9.24/test/3-copyFiles/data/res/hdpi/nested_dir/nested_file.txt000066400000000000000000000000501267257315000252270ustar00rootroot00000000000000hdpi/nested_dir/nested_file.txt content dub-0.9.24/test/3-copyFiles/data/res/i18n/000077500000000000000000000000001267257315000177255ustar00rootroot00000000000000dub-0.9.24/test/3-copyFiles/data/res/i18n/resource_en.txt000066400000000000000000000000301267257315000227700ustar00rootroot00000000000000i18n - english resourcesdub-0.9.24/test/3-copyFiles/data/res/i18n/resource_fr.txt000066400000000000000000000000301267257315000227750ustar00rootroot00000000000000i18n - french resources dub-0.9.24/test/3-copyFiles/data/res/ldpi/000077500000000000000000000000001267257315000200765ustar00rootroot00000000000000dub-0.9.24/test/3-copyFiles/data/res/ldpi/file1.txt000066400000000000000000000000231267257315000216320ustar00rootroot00000000000000ldpi/file1 content dub-0.9.24/test/3-copyFiles/data/res/ldpi/file2.txt000066400000000000000000000000231267257315000216330ustar00rootroot00000000000000ldpi/file2 content dub-0.9.24/test/3-copyFiles/data/res/ldpi/file3.txt000066400000000000000000000000231267257315000216340ustar00rootroot00000000000000ldpi/file3 content dub-0.9.24/test/3-copyFiles/data/res/mdpi/000077500000000000000000000000001267257315000200775ustar00rootroot00000000000000dub-0.9.24/test/3-copyFiles/data/res/mdpi/file1.txt000066400000000000000000000000231267257315000216330ustar00rootroot00000000000000mdpi/file1 content dub-0.9.24/test/3-copyFiles/data/res/mdpi/file2.txt000066400000000000000000000000231267257315000216340ustar00rootroot00000000000000mdpi/file2 content dub-0.9.24/test/3-copyFiles/data/res/mdpi/file3.txt000066400000000000000000000000231267257315000216350ustar00rootroot00000000000000mdpi/file3 content dub-0.9.24/test/3-copyFiles/dub.json000066400000000000000000000003101267257315000171030ustar00rootroot00000000000000{ "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-0.9.24/test/3-copyFiles/source/000077500000000000000000000000001267257315000167445ustar00rootroot00000000000000dub-0.9.24/test/3-copyFiles/source/app.d000066400000000000000000000021361267257315000176730ustar00rootroot00000000000000import 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-0.9.24/test/4-describe-data-1-list.sh000077500000000000000000000123321267257315000176460ustar00rootroot00000000000000#!/bin/bash set -e -o pipefail cd "$CURR_DIR"/describe-project temp_file=`mktemp` function cleanup { rm $temp_file } trap cleanup EXIT if ! $DUB describe --compiler=$COMPILER --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 '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 "crypto" >> "$expected_file" echo "curl" >> "$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_project" >> "$expected_file" echo "Have_describe_dependency_1" >> "$expected_file" echo "Have_describe_dependency_2" >> "$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 'The project data did not match the expected output!' fi dub-0.9.24/test/4-describe-data-2-dmd.sh000077500000000000000000000062661267257315000174510ustar00rootroot00000000000000#!/bin/bash set -e -o pipefail if ! dmd --help >/dev/null; then echo Skipping DMD-centric test on configuration that lacks DMD. exit fi cd "$CURR_DIR"/describe-project temp_file=`mktemp` function cleanup { rm $temp_file } trap cleanup EXIT if ! $DUB describe --compiler=dmd \ --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-lcrypto " >> "$expected_file" echo -n "-L-lcurl " >> "$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_project " >> "$expected_file" echo -n "-version=Have_describe_dependency_1 " >> "$expected_file" echo -n "-version=Have_describe_dependency_2 " >> "$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-0.9.24/test/4-describe-data-3-zero-delim.sh000077500000000000000000000071531267257315000207510ustar00rootroot00000000000000#!/bin/bash set -e -o pipefail cd "$CURR_DIR"/describe-project temp_file_normal=`mktemp` temp_file_zero_delim=`mktemp` function cleanup { rm $temp_file_normal rm $temp_file_zero_delim } trap cleanup EXIT # Test list-style project data if ! $DUB describe --compiler=$COMPILER --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=$COMPILER --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=$COMPILER --import-paths \ > "$temp_file_normal"; then die 'Printing --import-paths failed!' fi if ! $DUB describe --compiler=$COMPILER --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 ! dmd --help >/dev/null; then echo Skipping DMD-centric tests on configuration that lacks DMD. exit fi # Test dmd-style --data=versions if ! $DUB describe --compiler=dmd --data=versions \ > "$temp_file_normal"; then die 'Printing dmd-style --data=versions failed!' fi if ! $DUB describe --compiler=dmd --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=dmd --data=source-files \ > "$temp_file_normal"; then die 'Printing dmd-style --data=source-files failed!' fi if ! $DUB describe --compiler=dmd --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-0.9.24/test/4-describe-import-paths.sh000077500000000000000000000014631267257315000202600ustar00rootroot00000000000000#!/bin/bash set -e -o pipefail cd "$CURR_DIR"/describe-project temp_file=`mktemp` function cleanup { rm $temp_file } trap cleanup EXIT if ! $DUB describe --compiler=$COMPILER --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-0.9.24/test/4-describe-json.sh000077500000000000000000000003731267257315000166010ustar00rootroot00000000000000#!/bin/bash set -e -o pipefail cd "$CURR_DIR"/describe-project temp_file=`mktemp` function cleanup { rm $temp_file } trap cleanup EXIT if ! $DUB describe --compiler=$COMPILER > "$temp_file"; then die 'Printing describe JSON failed!' fi dub-0.9.24/test/4-describe-string-import-paths.sh000077500000000000000000000014541267257315000215640ustar00rootroot00000000000000#!/bin/bash set -e -o pipefail cd "$CURR_DIR"/describe-project temp_file=`mktemp` function cleanup { rm $temp_file } trap cleanup EXIT if ! $DUB describe --compiler=$COMPILER --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-0.9.24/test/custom-source-main-bug487/000077500000000000000000000000001267257315000201175ustar00rootroot00000000000000dub-0.9.24/test/custom-source-main-bug487/.gitignore000066400000000000000000000000461267257315000221070ustar00rootroot00000000000000.dub docs.json __dummy.html *.o *.obj dub-0.9.24/test/custom-source-main-bug487/.no_run000066400000000000000000000000001267257315000214060ustar00rootroot00000000000000dub-0.9.24/test/custom-source-main-bug487/.no_test000066400000000000000000000000001267257315000215610ustar00rootroot00000000000000dub-0.9.24/test/custom-source-main-bug487/dub.json000066400000000000000000000001331267257315000215610ustar00rootroot00000000000000{ "name": "custom-source-main-bug487", "sourcePaths": ["mysrc"], "dependencies": { } } dub-0.9.24/test/custom-source-main-bug487/mysrc/000077500000000000000000000000001267257315000212545ustar00rootroot00000000000000dub-0.9.24/test/custom-source-main-bug487/mysrc/app.d000066400000000000000000000000201267257315000221710ustar00rootroot00000000000000void main() { } dub-0.9.24/test/custom-unittest/000077500000000000000000000000001267257315000165365ustar00rootroot00000000000000dub-0.9.24/test/custom-unittest/dub.json000066400000000000000000000006021267257315000202010ustar00rootroot00000000000000{ "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-0.9.24/test/custom-unittest/source/000077500000000000000000000000001267257315000200365ustar00rootroot00000000000000dub-0.9.24/test/custom-unittest/source/app.d000066400000000000000000000001511267257315000207600ustar00rootroot00000000000000module app; import lib; import std.stdio; void main() { writeln("Running application."); libFunc(); } dub-0.9.24/test/custom-unittest/source/lib.d000066400000000000000000000001321267257315000207450ustar00rootroot00000000000000module lib; void libFunc() { import std.stdio; writefln("Library function called."); } dub-0.9.24/test/custom-unittest/test/000077500000000000000000000000001267257315000175155ustar00rootroot00000000000000dub-0.9.24/test/custom-unittest/test/main.d000066400000000000000000000001231267257315000206020ustar00rootroot00000000000000module main; void main() { import std.stdio; writefln("Running unit tests."); } dub-0.9.24/test/describe-dependency-1/000077500000000000000000000000001267257315000174015ustar00rootroot00000000000000dub-0.9.24/test/describe-dependency-1/.no_build000066400000000000000000000000021267257315000211650ustar00rootroot00000000000000 dub-0.9.24/test/describe-dependency-1/data/000077500000000000000000000000001267257315000203125ustar00rootroot00000000000000dub-0.9.24/test/describe-dependency-1/data/dummy-dep1.dat000066400000000000000000000000021267257315000227560ustar00rootroot00000000000000 dub-0.9.24/test/describe-dependency-1/dependency-postGenerateCommands.sh000077500000000000000000000000121267257315000261670ustar00rootroot00000000000000#!/bin/sh dub-0.9.24/test/describe-dependency-1/dependency-preGenerateCommands.sh000077500000000000000000000000121267257315000257700ustar00rootroot00000000000000#!/bin/sh dub-0.9.24/test/describe-dependency-1/dub.json000066400000000000000000000021111267257315000210410ustar00rootroot00000000000000{ "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": ["curl"], "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-0.9.24/test/describe-dependency-1/otherdir/000077500000000000000000000000001267257315000212215ustar00rootroot00000000000000dub-0.9.24/test/describe-dependency-1/otherdir/dummy.d000066400000000000000000000000021267257315000225110ustar00rootroot00000000000000 dub-0.9.24/test/describe-dependency-1/source/000077500000000000000000000000001267257315000207015ustar00rootroot00000000000000dub-0.9.24/test/describe-dependency-1/source/dummy.d000066400000000000000000000000021267257315000221710ustar00rootroot00000000000000 dub-0.9.24/test/describe-dependency-2/000077500000000000000000000000001267257315000174025ustar00rootroot00000000000000dub-0.9.24/test/describe-dependency-2/.no_build000066400000000000000000000000021267257315000211660ustar00rootroot00000000000000 dub-0.9.24/test/describe-dependency-2/dub.json000066400000000000000000000005341267257315000210510ustar00rootroot00000000000000{ "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-0.9.24/test/describe-dependency-2/some-extra-string-import-path/000077500000000000000000000000001267257315000252345ustar00rootroot00000000000000dub-0.9.24/test/describe-dependency-2/some-extra-string-import-path/dummy.d000066400000000000000000000000021267257315000265240ustar00rootroot00000000000000 dub-0.9.24/test/describe-dependency-2/some-path/000077500000000000000000000000001267257315000212775ustar00rootroot00000000000000dub-0.9.24/test/describe-dependency-2/some-path/dummy.d000066400000000000000000000000021267257315000225670ustar00rootroot00000000000000 dub-0.9.24/test/describe-dependency-3/000077500000000000000000000000001267257315000174035ustar00rootroot00000000000000dub-0.9.24/test/describe-dependency-3/.no_build000066400000000000000000000000021267257315000211670ustar00rootroot00000000000000 dub-0.9.24/test/describe-dependency-3/dep3-source/000077500000000000000000000000001267257315000215345ustar00rootroot00000000000000dub-0.9.24/test/describe-dependency-3/dep3-source/dummy.d000066400000000000000000000000021267257315000230240ustar00rootroot00000000000000 dub-0.9.24/test/describe-dependency-3/dep3-string-import-path/000077500000000000000000000000001267257315000240045ustar00rootroot00000000000000dub-0.9.24/test/describe-dependency-3/dep3-string-import-path/dummy.d000066400000000000000000000000021267257315000252740ustar00rootroot00000000000000 dub-0.9.24/test/describe-dependency-3/dub.json000066400000000000000000000006341267257315000210530ustar00rootroot00000000000000{ "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-0.9.24/test/describe-project/000077500000000000000000000000001267257315000165735ustar00rootroot00000000000000dub-0.9.24/test/describe-project/.no_build000066400000000000000000000000021267257315000203570ustar00rootroot00000000000000 dub-0.9.24/test/describe-project/data/000077500000000000000000000000001267257315000175045ustar00rootroot00000000000000dub-0.9.24/test/describe-project/data/dummy.dat000066400000000000000000000000021267257315000213210ustar00rootroot00000000000000 dub-0.9.24/test/describe-project/do-postGenerateCommands.sh000077500000000000000000000000121267257315000236450ustar00rootroot00000000000000#!/bin/sh dub-0.9.24/test/describe-project/do-preGenerateCommands.sh000077500000000000000000000000121267257315000234460ustar00rootroot00000000000000#!/bin/sh dub-0.9.24/test/describe-project/dub.json000066400000000000000000000027561267257315000202520ustar00rootroot00000000000000{ "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": ["crypto"], "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-0.9.24/test/describe-project/src/000077500000000000000000000000001267257315000173625ustar00rootroot00000000000000dub-0.9.24/test/describe-project/src/dummy.d000066400000000000000000000000021267257315000206520ustar00rootroot00000000000000 dub-0.9.24/test/describe-project/views/000077500000000000000000000000001267257315000177305ustar00rootroot00000000000000dub-0.9.24/test/describe-project/views/dummy.d000066400000000000000000000000021267257315000212200ustar00rootroot00000000000000 dub-0.9.24/test/ignore-hidden-1/000077500000000000000000000000001267257315000162215ustar00rootroot00000000000000dub-0.9.24/test/ignore-hidden-1/.gitignore000066400000000000000000000000461267257315000202110ustar00rootroot00000000000000.dub docs.json __dummy.html *.o *.obj dub-0.9.24/test/ignore-hidden-1/.no_run000066400000000000000000000000001267257315000175100ustar00rootroot00000000000000dub-0.9.24/test/ignore-hidden-1/.no_test000066400000000000000000000000001267257315000176630ustar00rootroot00000000000000dub-0.9.24/test/ignore-hidden-1/dub.json000066400000000000000000000000401267257315000176600ustar00rootroot00000000000000{ "name": "ignore-hidden-1", } dub-0.9.24/test/ignore-hidden-1/source/000077500000000000000000000000001267257315000175215ustar00rootroot00000000000000dub-0.9.24/test/ignore-hidden-1/source/.hidden.d000066400000000000000000000002131267257315000211730ustar00rootroot00000000000000// need module declarations as '.' is not allowed in module names module hidden; static assert(0, "Dub should not compile "~__FILE__~"."); dub-0.9.24/test/ignore-hidden-1/source/app.d000066400000000000000000000000201267257315000204360ustar00rootroot00000000000000void main() { } dub-0.9.24/test/ignore-hidden-2/000077500000000000000000000000001267257315000162225ustar00rootroot00000000000000dub-0.9.24/test/ignore-hidden-2/.gitignore000066400000000000000000000000461267257315000202120ustar00rootroot00000000000000.dub docs.json __dummy.html *.o *.obj dub-0.9.24/test/ignore-hidden-2/.no_run000066400000000000000000000000001267257315000175110ustar00rootroot00000000000000dub-0.9.24/test/ignore-hidden-2/.no_test000066400000000000000000000000001267257315000176640ustar00rootroot00000000000000dub-0.9.24/test/ignore-hidden-2/dub.json000066400000000000000000000001061267257315000176640ustar00rootroot00000000000000{ "name": "ignore-hidden-2", "sourceFiles": ["source/.hidden.d"], } dub-0.9.24/test/ignore-hidden-2/source/000077500000000000000000000000001267257315000175225ustar00rootroot00000000000000dub-0.9.24/test/ignore-hidden-2/source/.hidden.d000066400000000000000000000000171267257315000211760ustar00rootroot00000000000000module hidden; dub-0.9.24/test/ignore-hidden-2/source/app.d000066400000000000000000000000401267257315000204410ustar00rootroot00000000000000import hidden; void main() { } dub-0.9.24/test/issue564-invalid-upgrade-dependency.sh000077500000000000000000000002611267257315000224610ustar00rootroot00000000000000#!/bin/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=${COMPILER} main || exit 1 dub-0.9.24/test/issue564-invalid-upgrade-dependency/000077500000000000000000000000001267257315000221235ustar00rootroot00000000000000dub-0.9.24/test/issue564-invalid-upgrade-dependency/.no_build000066400000000000000000000000001267257315000237050ustar00rootroot00000000000000dub-0.9.24/test/issue564-invalid-upgrade-dependency/.no_run000066400000000000000000000000001267257315000234120ustar00rootroot00000000000000dub-0.9.24/test/issue564-invalid-upgrade-dependency/.no_test000066400000000000000000000000001267257315000235650ustar00rootroot00000000000000dub-0.9.24/test/issue564-invalid-upgrade-dependency/a-1.0.0/000077500000000000000000000000001267257315000227755ustar00rootroot00000000000000dub-0.9.24/test/issue564-invalid-upgrade-dependency/a-1.0.0/dub.json000066400000000000000000000000471267257315000244430ustar00rootroot00000000000000{ "name": "a", "version": "1.0.0", } dub-0.9.24/test/issue564-invalid-upgrade-dependency/a-1.0.0/source/000077500000000000000000000000001267257315000242755ustar00rootroot00000000000000dub-0.9.24/test/issue564-invalid-upgrade-dependency/a-1.0.0/source/a.d000066400000000000000000000000211267257315000246530ustar00rootroot00000000000000void test() { }dub-0.9.24/test/issue564-invalid-upgrade-dependency/a-1.1.0/000077500000000000000000000000001267257315000227765ustar00rootroot00000000000000dub-0.9.24/test/issue564-invalid-upgrade-dependency/a-1.1.0/dub.json000066400000000000000000000001361267257315000244430ustar00rootroot00000000000000{ "name": "a", "version": "1.1.0", "dependencies": { "invalid": {"path": "invalid"} } } dub-0.9.24/test/issue564-invalid-upgrade-dependency/a-1.1.0/source/000077500000000000000000000000001267257315000242765ustar00rootroot00000000000000dub-0.9.24/test/issue564-invalid-upgrade-dependency/a-1.1.0/source/a.d000066400000000000000000000000211267257315000246540ustar00rootroot00000000000000void test() { }dub-0.9.24/test/issue564-invalid-upgrade-dependency/main/000077500000000000000000000000001267257315000230475ustar00rootroot00000000000000dub-0.9.24/test/issue564-invalid-upgrade-dependency/main/dub.json000066400000000000000000000000721267257315000245130ustar00rootroot00000000000000{ "name": "main", "dependencies": { "a": "~>1.0" } } dub-0.9.24/test/issue564-invalid-upgrade-dependency/main/dub.selections.json000066400000000000000000000000701267257315000266600ustar00rootroot00000000000000{ "fileVersion": 1, "versions": { "a": "1.0.0" } } dub-0.9.24/test/issue564-invalid-upgrade-dependency/main/source/000077500000000000000000000000001267257315000243475ustar00rootroot00000000000000dub-0.9.24/test/issue564-invalid-upgrade-dependency/main/source/app.d000066400000000000000000000000521267257315000252710ustar00rootroot00000000000000import a; void main() { test(); } dub-0.9.24/test/issue586-subpack-dep.sh000077500000000000000000000003201267257315000174700ustar00rootroot00000000000000#!/bin/sh cd ${CURR_DIR}/issue586-subpack-dep rm -rf a/.dub rm -rf a/b/.dub rm -rf main/.dub ${DUB} build --bare --compiler=${COMPILER} main || exit 1 ${DUB} run --bare --compiler=${COMPILER} main || exit 1 dub-0.9.24/test/issue586-subpack-dep/000077500000000000000000000000001267257315000171365ustar00rootroot00000000000000dub-0.9.24/test/issue586-subpack-dep/.no_build000066400000000000000000000000001267257315000207200ustar00rootroot00000000000000dub-0.9.24/test/issue586-subpack-dep/.no_run000066400000000000000000000000001267257315000204250ustar00rootroot00000000000000dub-0.9.24/test/issue586-subpack-dep/.no_test000066400000000000000000000000001267257315000206000ustar00rootroot00000000000000dub-0.9.24/test/issue586-subpack-dep/a/000077500000000000000000000000001267257315000173565ustar00rootroot00000000000000dub-0.9.24/test/issue586-subpack-dep/a/b/000077500000000000000000000000001267257315000175775ustar00rootroot00000000000000dub-0.9.24/test/issue586-subpack-dep/a/b/dub.sdl000066400000000000000000000000111267257315000210450ustar00rootroot00000000000000name "b" dub-0.9.24/test/issue586-subpack-dep/a/b/source/000077500000000000000000000000001267257315000210775ustar00rootroot00000000000000dub-0.9.24/test/issue586-subpack-dep/a/b/source/b.d000066400000000000000000000000431267257315000214620ustar00rootroot00000000000000module b; int bfun() { return 2; }dub-0.9.24/test/issue586-subpack-dep/a/dub.sdl000066400000000000000000000000651267257315000206350ustar00rootroot00000000000000name "a" dependency ":b" version="*" subPackage "b/" dub-0.9.24/test/issue586-subpack-dep/a/source/000077500000000000000000000000001267257315000206565ustar00rootroot00000000000000dub-0.9.24/test/issue586-subpack-dep/a/source/a.d000066400000000000000000000000711267257315000212410ustar00rootroot00000000000000module a; import b; int afun() { return 1 + bfun(); } dub-0.9.24/test/issue586-subpack-dep/main/000077500000000000000000000000001267257315000200625ustar00rootroot00000000000000dub-0.9.24/test/issue586-subpack-dep/main/dub.sdl000066400000000000000000000000761267257315000213430ustar00rootroot00000000000000name "main" dependency "a" version="*" targetType "executable"dub-0.9.24/test/issue586-subpack-dep/main/dub.selections.json000066400000000000000000000000721267257315000236750ustar00rootroot00000000000000{ "fileVersion": 1, "versions": { "a": "~master" } } dub-0.9.24/test/issue586-subpack-dep/main/source/000077500000000000000000000000001267257315000213625ustar00rootroot00000000000000dub-0.9.24/test/issue586-subpack-dep/main/source/c.d000066400000000000000000000000741267257315000217520ustar00rootroot00000000000000module c; import a; void main() { assert(afun() == 3); } dub-0.9.24/test/issue613-dynlib-pic.sh000077500000000000000000000003151267257315000173170ustar00rootroot00000000000000#!/bin/sh cd ${CURR_DIR}/issue613-dynlib-pic rm -rf .dub if [ "${COMPILER}" = "dmd" ]; then ${DUB} build --compiler=${COMPILER} || exit 1 else echo "Skipping shared library test for ${COMPILER}..." fi dub-0.9.24/test/issue613-dynlib-pic/000077500000000000000000000000001267257315000167615ustar00rootroot00000000000000dub-0.9.24/test/issue613-dynlib-pic/.gitignore000066400000000000000000000000461267257315000207510ustar00rootroot00000000000000.dub docs.json __dummy.html *.o *.obj dub-0.9.24/test/issue613-dynlib-pic/.no_build000066400000000000000000000000001267257315000205430ustar00rootroot00000000000000dub-0.9.24/test/issue613-dynlib-pic/.no_run000066400000000000000000000000001267257315000202500ustar00rootroot00000000000000dub-0.9.24/test/issue613-dynlib-pic/.no_test000066400000000000000000000000001267257315000204230ustar00rootroot00000000000000dub-0.9.24/test/issue613-dynlib-pic/dub.sdl000066400000000000000000000002601267257315000202350ustar00rootroot00000000000000name "issue613-dynlib-pic" targetType "dynamicLibrary" // TODO: instead of just testing build success, test if -shared, -fPIC and -defaultlib have all been specified correctlydub-0.9.24/test/issue613-dynlib-pic/source/000077500000000000000000000000001267257315000202615ustar00rootroot00000000000000dub-0.9.24/test/issue613-dynlib-pic/source/app.d000066400000000000000000000000211267257315000211770ustar00rootroot00000000000000void test() { }dub-0.9.24/test/path-subpackage-ref/000077500000000000000000000000001267257315000171605ustar00rootroot00000000000000dub-0.9.24/test/path-subpackage-ref/dub.json000066400000000000000000000001441267257315000206240ustar00rootroot00000000000000{ "name": "test", "dependencies": { "test:subpack": "*" }, "subPackages": [ "subpack/" ] } dub-0.9.24/test/path-subpackage-ref/source/000077500000000000000000000000001267257315000204605ustar00rootroot00000000000000dub-0.9.24/test/path-subpackage-ref/source/app.d000066400000000000000000000000651267257315000214060ustar00rootroot00000000000000module app; import lib; void main() { libFunc(); } dub-0.9.24/test/path-subpackage-ref/subpack/000077500000000000000000000000001267257315000206105ustar00rootroot00000000000000dub-0.9.24/test/path-subpackage-ref/subpack/dub.json000066400000000000000000000002371267257315000222570ustar00rootroot00000000000000{ "name": "subpack", "description": "A minimal D application.", "copyright": "Copyright © 2014, sludwig", "authors": ["sludwig"], "dependencies": { } } dub-0.9.24/test/path-subpackage-ref/subpack/source/000077500000000000000000000000001267257315000221105ustar00rootroot00000000000000dub-0.9.24/test/path-subpackage-ref/subpack/source/lib.d000066400000000000000000000001141267257315000230170ustar00rootroot00000000000000import std.stdio; void libFunc() { writeln("Library function called."); } dub-0.9.24/test/run-unittest.sh000077500000000000000000000031431267257315000163700ustar00rootroot00000000000000#!/bin/bash function die() { echo -e 1>&2 "\033[0;31m"$@"\033[0m" exit 1 } export -f die function log() { echo -e "\033[0;33m[INFO] "$@"\033[0m" } export -f log if [ -z ${DUB} ]; then die 'Error: Variable $DUB must be defined to run the tests.' fi if [ -z ${COMPILER} ]; then log '$COMPILER not defined, assuming dmd...' COMPILER=dmd fi CURR_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) for script in $(ls $CURR_DIR/*.sh); do if [ "$script" = "$(readlink -f ${BASH_SOURCE[0]})" ]; then continue; fi log "Running $script..." DUB=$DUB COMPILER=$COMPILER CURR_DIR="$CURR_DIR" $script || die "Script failure." done for pack in $(ls -d $CURR_DIR/*/); do # First we build the packages if [ ! -e $pack/.no_build ]; then # For sourceLibrary if [ -e $pack/.fail_build ]; then log "Building $pack, expected failure..." $DUB build --force --root=$pack --compiler=$COMPILER 2>/dev/null && die "Error: Failure expected, but build passed." else log "Building $pack..." $DUB build --force --root=$pack --compiler=$COMPILER || die "Build failure." fi fi # We run the ones that are supposed to be runned if [ ! -e $pack/.no_build ] && [ ! -e $pack/.no_run ]; then log "Running $pack..." $DUB run --force --root=$pack --compiler=$COMPILER || die "Run failure." fi # Finally, the unittest part if [ ! -e $pack/.no_build ] && [ ! -e $pack/.no_test ]; then log "Testing $pack..." $DUB test --force --root=$pack --compiler=$COMPILER || die "Test failure." fi done dub-0.9.24/test/sdl-package-simple/000077500000000000000000000000001267257315000170115ustar00rootroot00000000000000dub-0.9.24/test/sdl-package-simple/dub.sdl000066400000000000000000000000551267257315000202670ustar00rootroot00000000000000name "exec-simple"; targetType "executable"; dub-0.9.24/test/sdl-package-simple/source/000077500000000000000000000000001267257315000203115ustar00rootroot00000000000000dub-0.9.24/test/sdl-package-simple/source/app.d000066400000000000000000000000761267257315000212410ustar00rootroot00000000000000import std.stdio; void main() { writeln(__FUNCTION__); } dub-0.9.24/test/subpackage-ref/000077500000000000000000000000001267257315000162265ustar00rootroot00000000000000dub-0.9.24/test/subpackage-ref/dub.json000066400000000000000000000001641267257315000176740ustar00rootroot00000000000000{ "name": "test", "dependencies": { "test:subpack": "*" }, "subPackages": [ { "name": "subpack" } ] } dub-0.9.24/test/subpackage-ref/source/000077500000000000000000000000001267257315000175265ustar00rootroot00000000000000dub-0.9.24/test/subpackage-ref/source/app.d000066400000000000000000000001311267257315000204460ustar00rootroot00000000000000import std.stdio; void main() { writeln("Edit source/app.d to start your project."); } dub-0.9.24/test/test-version-opt.sh000077500000000000000000000000651267257315000171510ustar00rootroot00000000000000#!/bin/bash $DUB --version | grep -qF 'DUB version' dub-0.9.24/travis-ci.sh000077500000000000000000000006601267257315000146320ustar00rootroot00000000000000#!/bin/bash set -e -o pipefail dub test --compiler=${DC} -c library-nonet if [ "$COVERAGE" = true ]; then # library-nonet fails to build with coverage (Issue 13742) dub test --compiler=${DC} -b unittest-cov ./build.sh -cov else ./build.sh fi DUB=`pwd`/bin/dub COMPILER=${DC} test/run-unittest.sh if [ "$COVERAGE" = true ]; then dub fetch doveralls --version=~master dub run doveralls --compiler=${DC} fi